home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 3 / ACE CD 3.iso / files / docs / real3ddo.lha / Real3DPart4.doc < prev    next >
Text File  |  1994-11-27  |  151KB  |  4,875 lines

  1.  
  2.  
  3.                                 PART 4
  4.  
  5.  
  6.  
  7.                   - TUTORIAL 6.54 -
  8.  
  9. Figure T6-62: Parallel Waves  (PICTURE: T6-62)
  10.  
  11. Play the animation and the method generates waves in "x" direction.
  12.  
  13. 6.23.4 Waves and Ripples
  14.  
  15. Of course, it is possible to create more than one WAVE method at the same
  16. level, in which case the generated waves will interfere with each other.
  17. In other words, the result wave is the sum of the component waves. Because
  18. the size of the parameters for wave methods defines the wave-length and
  19. -height, this feature can be used for example for generating "ripples" on
  20. waves.
  21.  
  22. So, let's create two wave methods generating parallel waves perpendicular
  23. to each other.
  24.  
  25. 1. Create parallel waves as described in the previous example.
  26.  
  27. 2. Duplicate the method object, rotate it and make it much smaller.
  28.  
  29. Figure T6-63: Interfering Waves  (PICTURE: T6-63)
  30.  
  31. Play the animation and there will be small waves in the big waves.
  32.  
  33. 6.23.5 Waving Particles
  34.  
  35. This example demonstrates how the wave method can be used for waving a
  36. set of primitives instead of a mesh.
  37.  
  38. If the target object is not a freeform object, then it is treated as a
  39. "point" of a freeform object. Instead of using one freeform target for the
  40. method, we can use hundreds of primitives.
  41.  
  42. So, let' s create an example where the wave method is applied to a number
  43. of spheres:
  44.  
  45. 1. Create a line consisting of small spheres.
  46.  
  47. 2. Create a WAVE method to the same level with the spheres.
  48.  
  49. 3. Create a coordsys and a circle under the method.
  50.  
  51. 4. Play the animation.
  52.  
  53.                              - TUTORIAL 6.55 -
  54.  
  55. Figure T6-64: Waving Particles  (PICTURE: T6-64)
  56.  
  57.                              - TUTORIAL 6.56 -
  58.  
  59. Chapter 7 RPL
  60. -------------
  61.  
  62. 7.1 INTRODUCTION
  63.  
  64. RPL stands for REAL 3D Programming Language. It is a FORTH-like language
  65. integrated into the REAL 3D environment. It is a full featured programming
  66. language which provides you with power, flexibility and total control over
  67. all the features of REAL 3D.
  68.  
  69. The language has three main uses: as a method for storing macros, as a
  70. file format for importing and exporting all the information needed to
  71. describe the scenes and animations you create, and as a programming
  72. interface to allow you to expand the functions of REAL 3D to fulfill any
  73. requirements you might have.
  74.  
  75. Because RPL is meant to be used for expanding the REAL 3D program, it has
  76. been designed to be as fast in its execution as possible. It is also
  77. capable of making direct access to the Operating System. For these
  78. reasons, it is quite a low level language. However, considerable effort
  79. has been devoted to make it easy to learn with the intention of all users
  80. being able to make use of it.
  81.  
  82. This section is intended to introduce you to RPL programming as easily as
  83. possible; but some understanding of basic computer programming principles
  84. has been assumed. If after reading through the introduction and working
  85. through the tutorial section you do not feel you have a full understanding
  86. of how to use RPL then there are many good books on introductory
  87. programming. Any that directly relate to FORTH will provide the best
  88. assistance, and most if not all the examples will work in RPL.
  89.  
  90. 7.1.1 Basic Concepts
  91.  
  92. First some RPL terminology to get started:
  93.  
  94. Word
  95. A word is a collection of constants and references to previously defined
  96. words that are to be executed when the word is run; like a procedure or
  97. function in the languages "C" or Pascal.
  98.  
  99. Vocabulary
  100. This is the collection of all defined words, variables and named
  101. constants.
  102.  
  103. Stack
  104. This is an area of memory used by the RPL system for storing the
  105. information it needs to process the words you want to execute and the
  106. operands those words need for their execution.
  107.  
  108. RPL, like FORTH, is a threaded language. Threaded languages grow
  109. incrementally; you define new words using existing words that are either
  110. predefined (standard RPL words) or words that you have defined earlier.
  111.  
  112. RPL is interactive, it executes or compiles words the instant they are
  113. entered. New words become a part of the RPL vocabulary as soon as their
  114. definitions are completed. They can then be executed just by typing in
  115. their names and pressing <ENTER>, or they can be included in the
  116. definitions of new words. Words must be entered exactly as they appear in
  117. the vocabulary, upper-case letters must be upper-case and lower-case must
  118. be entered as lower-case. They must also be entered in full, they cannot
  119. be abbreviated in any way.
  120.  
  121.                              - TUTORIAL 7.1 -
  122.  
  123. 7.2 TUTORIAL
  124.  
  125. 7.2.1 Getting Started
  126.  
  127. To start your introduction to RPL the first step you must take is to open
  128. an RPL Window. Select PROJECT/Windows/RPL and a window very similar to an
  129. OS shell window will open. Through this window you will pass information
  130. to the RPL system and it can pass information back to you.
  131.  
  132. To examine the interactive nature of RPL and for you to get started try
  133. the following simple examples. Remember to enter the words EXACTLY as
  134. they appear in the examples!
  135.  
  136. Example 1: Print a number.
  137.  
  138. Type the following text exactly as it is shown:
  139.  
  140.      2.
  141.  
  142. When you press <ENTER> RPL will respond:
  143.  
  144.      2
  145.  
  146. Note:
  147. You just asked RPL to print out the number "2". The character "." is a
  148. predefined command or word in RPL's vocabulary which prints out an integer
  149. value.
  150.  
  151. Example 2: Print some text.
  152.  
  153. Now enter the following line:
  154.  
  155.      "hello world" PUTS
  156.  
  157. RPL responds:
  158.  
  159.      hello world
  160.  
  161. Note:
  162. The word "PUTS" (Put String) is another predefined word which printed the
  163. text "hello world".
  164.  
  165. Before you test any further examples some explanation of how RPL operates
  166. is necessary.
  167.  
  168. 7.2.2 Stacks
  169.  
  170. RPL is a stack oriented language. This means that RPL uses stacks to store
  171. operands, intermediate results and return addresses.
  172.  
  173. RPL uses four stacks. The Parameter Stack holds arguments for RPL words as
  174. well as results after executing those words. The Return Stack holds
  175. addresses of locations from where other RPL words were called, so that
  176. program execution can return to the location from where the calls were
  177. made. The other two stacks are only used internally. The Control Stack is
  178. used to check that the structure of the word is correct and all flow
  179. control structures are balanced while compiling a new word. The Vocabulary
  180. Stack stores the references to the compiled words that form the RPL
  181. vocabulary.
  182.  
  183. These stacks work in Last In First Out (LIFO) manner, which is explained
  184. below in "Parameter Stack".
  185.  
  186. 7.2.3 Reverse Polish Notation
  187.  
  188. RPL uses postfix-notation, also known as Reverse Polish Notation (RPN).
  189.  
  190. In RPN the arguments, or operands, are pushed onto stack first and then an
  191. operation is applied to them. The result is left on top of the stack, and
  192. can be used in consecutive operations.
  193.  
  194. The conversion from algebraic notation (the way you write mathematical
  195. expressions on paper) to RPN is quite natural.
  196.  
  197. You start with the operands you would start with if you were doing the
  198. calculation manually, and then append an operator.
  199.  
  200. Then you take other operands and apply other operations until all the
  201. operands and operations are used. That may sound difficult but a couple
  202. of examples should clarify the point.
  203.  
  204.                              - TUTORIAL 7.2 -
  205.  
  206. Example 3: Convert 12 + 5 + 2 to RPN.
  207.  
  208. 1. Manually you would first add 5 to 12. Therefore you write:
  209.  
  210.      12 5 +
  211.  
  212. Remember, the operands come first and then
  213. the operator.
  214.  
  215. 2. Then you would add 2 to the result of the previous addition.
  216.  
  217.      2 +
  218.  
  219. Note:
  220. Both "+" operators require two operands. The first addition uses 12 and 5
  221. but the second "+" seem to have only one operand, the number 2. The second
  222. addition takes the result of the first addition as its second operand.
  223. How the result of the first operation is preserved will be explained in
  224. the section about the Parameter Stack.
  225.  
  226. So the whole expression in RPN is:
  227.  
  228.      12 5 + 2 +
  229.  
  230. 3. Finally you will use the "." word to print the result; so that the RPL
  231.    text becomes:
  232.  
  233.      12 5 + 2 + .
  234.  
  235. And RPL responds by printing the result:
  236.  
  237.      19
  238.  
  239. Example 4: Convert 2 + 5 * 7 to RPN.
  240.  
  241. 1. First you multiply 5 with 7 and then add 2 to the result.
  242.    So in RPL you enter:
  243.  
  244.      5 7 * 2 + .
  245.  
  246. 7.2.4 Parameter Stack
  247.  
  248. When RPL scans input, whether it comes from the keyboard or from a file,
  249. it uses the Parameter Stack to store all operands it detects. This will
  250. be just called "the stack" for brevity, when there's no risk of confusing
  251. it with the Return stack.
  252.  
  253. There are three kinds of operands in the RPL system: integer , floating-
  254. point, and address. The address operands can be addresses of RPL words, or
  255. addresses of variables (integer or floating-point) or generic addresses,
  256. addresses to any kind of value you want. All the addresses are handled in
  257. the same way. That is to say that RPL makes no distinction between
  258. addresses of different types of items.
  259.  
  260. The stack operates on the basis of the last operand in will be the first
  261. out. This is the LIFO principle as mentioned. If you picture the stack
  262. as a pile of bricks (or any other neatly stackable material), you put new
  263. bricks on the top of the pile and also take them off from the top.
  264.  
  265. So how are operands put onto the stack? Just enter them, and they are
  266. "pushed" onto the stack so that the last entered number will be the top-
  267. most one. In Example 1, you pushed one operand onto the stack (number 2).
  268. Then the command "." pulled it off and printed it in your RPL window.
  269.  
  270. Now push several operands onto the stack,
  271.  
  272. Try the following:
  273.  
  274.      1
  275.      2
  276.      3
  277.  
  278. You pushed three numbers onto the stack. Print them all out by entering
  279. three "." commands and RPL responds:
  280.  
  281.      3
  282.      2
  283.      1
  284.  
  285.                              - TUTORIAL 7.3 -
  286.  
  287. Try to enter "." command once more time and RPL will respond:
  288.  
  289.      STACK EMPTY
  290.  
  291. There were no more operands left on the stack for RPL to print.
  292.  
  293. You get the same error message if you, for whatever reason, try to pull a
  294. value from the stack when none are available. This would occur if you had
  295. two integers on the stack and entered the "+" word twice.
  296.  
  297. The second "+" has only one stack item and the error message is given.
  298.  
  299. Now examine what happened to the stack for Example 3. Diagrams will be
  300. used to illustrate what is happening with the stack as each step is
  301. interpreted.
  302.  
  303. 1. Suppose you start with an empty stack.
  304.  
  305. 2. The RPL statement "12 5 + 2 + ." was scanned by the RPL interpreter.
  306.  
  307. 3. First, 12 was pushed to stack.
  308.  
  309.      +----+ <- top of stack
  310.      | 12 |
  311.      +----+
  312.  
  313. 4. Then 5 was pushed on stack
  314.  
  315.      +----+<- top of stack
  316.      | 5  |
  317.      +----+
  318.      | 12 |
  319.      +----+
  320.  
  321. 5. The "+" was scanned, which, because it is a executable word not an
  322.    operand, is executed. The word "+" pops (takes off) the first two
  323.    operands from the stack, then adds them and pushes the result back
  324.    onto the stack.
  325.  
  326.      +----+
  327.      | 17 |
  328.      +----+
  329.  
  330. 6. Then 2 was pushed on stack
  331.  
  332.      +----+
  333.      | 2  |
  334.      +----+
  335.      | 17 |
  336.      +----+
  337.  
  338. 7. The last "+" was scanned, the top two stack items are added, resulting
  339.    in the following stack situation:
  340.  
  341.      +----+
  342.      | 19 |
  343.      +----+
  344.  
  345. 8. Finally the "." was scanned and interpreted and the value is printed
  346.    leaving the stack in its initial empty state.
  347.  
  348. Note:
  349. RPL words must be separated from each other and their operands by either
  350. a <SPACE> or <ENTER>, but using <ENTER> also passes the current line to
  351. the RPL system and it will be interpreted immediately. So the example
  352. above could also have been entered as:
  353.  
  354.      12
  355.      5
  356.      +
  357.      2
  358.      +
  359.      .
  360.  
  361. 7.2.5 DataTypes
  362.  
  363. There are three kinds of data types in the RPL system: integer, floating-
  364. point and string. These are often refered to as literals. In order to
  365. enter values on the operand stack, you type in literals separated by
  366. <SPACE> or <ENTER> just as you have done in the examples above.
  367.  
  368. Integers can contain only integral values, such as -3, 0 and 12, while
  369. floating-point numbers can be used for representing decimal numbers like
  370. -1.2, 0.12 and 1243.1.
  371.  
  372.                              - TUTORIAL 7.4 -
  373.  
  374. 7.2.5.1 integers
  375.  
  376. Integer literals begin with a optional sign (+ or -) and contain only
  377. decimal digits. So far you have only used integer arithmetic, with integer
  378. literals and their corresponding integer operator words.
  379.  
  380. 7.2.5.2 Floating-points
  381.  
  382. Floating-point literals are similar to integer literals but they contain
  383. a decimal point or a exponent separator or both. The exponent separator
  384. can be either "e" or "E". The exponant can then contain an optional sign.
  385.  
  386. As you would expect, arithmetic operations can also be carried out with
  387. floating-point values. There are separate words to carry out these
  388. operations:
  389.  
  390.      F+  - add two floating-point values
  391.      F-  - subtract
  392.      F*  - multiply
  393.      F/  - divide
  394.      F.  - print
  395.      Fxx - etc.
  396.  
  397. Example 5:
  398.  
  399. Enter the following text:
  400.  
  401.      100.0 0.5 F* F.
  402.  
  403. RPL replies:
  404.  
  405.      50.0000
  406.  
  407. It did that because you pushed two floating-point values onto the stack
  408. then multiplied them as floating-points and finally printed out the
  409. return value from the "F*" word, as a floating-point.
  410.  
  411. Example 6:
  412.  
  413. Now try the following:
  414.  
  415.      123
  416.      F.
  417.  
  418. and RPL responds with:
  419.  
  420.      123.0000
  421.  
  422. This demonstrates an important principle of RPL. RPL uses Object-
  423. Orientation Theory to handle the operands on the stack. This means that it
  424. knows the data type of each stack value and the data type it requires for
  425. each operand of a word and handles them accordingly. In Example 6 above,
  426. when the command "F." pulled the integer value 123 off the stack, it
  427. converted the value to the required type before it tried to use it.
  428.  
  429. This also works if words requiring integer operands receive floating-point
  430. values.
  431.  
  432. Example 7:
  433.  
  434. When you enter:
  435.  
  436.      6.8
  437.      .
  438.  
  439. RPL will respond with:
  440.  
  441.      7
  442.  
  443. The RPL word "." works with integers, it had to convert the floating-
  444. point value it pulled from the stack to an integer before it printed it;
  445. because integers cannot contain any fractional part the value was rounded
  446. to the nearest integer value.
  447.  
  448. 7.2.5.3 STRINGS
  449.  
  450. String literals begin and end with a double quote character. If a
  451. double-quote is wanted in a string literal, it should be preceded by a
  452. back-slash.
  453.  
  454.                              - TUTORIAL 7.5 -
  455.  
  456. For example:
  457.  
  458.      "This string contains a \"."
  459.  
  460. Will be interpreted as:
  461.  
  462.      This string contains a ".
  463.  
  464. If a back-slash is required then two must be entered consecutively.
  465.  
  466. For example:
  467.  
  468.      "This string contains a \\."
  469.  
  470. Will be interpreted as:
  471.  
  472.      This string contains a \.
  473.  
  474. RPL handles strings slightly differently from the way the integers and
  475. floating-points are treated. With integer and floating-point literals
  476. the numerical value is pushed on stack, and with string literals the
  477. address of the first character of the string is placed on the stack.
  478.  
  479. You have already encountered the string printing word "PUTS". Let's look
  480. at how it actually operates.
  481.  
  482. Consider the RPL text:
  483.  
  484.      "Hello, this is a string" PUTS
  485.  
  486. 1. When the string "Hello, this is a string" was typed, RPL did NOT push
  487.    the entire string onto the stack. Instead the address of the string was
  488.    pushed. The memory for the string itself was allocated from elsewhere.
  489.  
  490. 2. The word "PUTS" then pulls the address out off the stack and copies the
  491.    string from that address to the window. Every character has a
  492.    corresponding value, which is used for representing the character, this
  493.    is called the ASCII code. For example, the ASCII code for the character
  494.    "!" is 33. So, when RPL stores the character "!", it actually stores
  495.    the value 33. The RPL word "EMIT" can be used for printing out
  496.    characters by supplying ASCII code for them as operands.
  497.  
  498. Example 8:
  499.  
  500. Enter the following:
  501.  
  502.      33 EMIT
  503.  
  504. and RPL replies:
  505.  
  506.      !
  507.  
  508. So, you can store a simple string onto the stack and print it out using
  509. the EMIT function.
  510.  
  511. Example 9:
  512.  
  513. Enter:
  514.  
  515.      76 80 82 EMIT EMIT EMIT
  516.  
  517. and RPL replies:
  518.  
  519.      RPL
  520.  
  521. Finally , you can investigate one property of string literals that might
  522. not be immediately obvious.
  523.  
  524. As you just learned, entering a string caused RPL to allocate the memory
  525. for the string and push the address of it onto the stack. To be precise,
  526. the address of the first character is pushed onto the stack. This means
  527. that it is possible to use arithmetic operations to select part of a
  528. string.
  529.  
  530. Example 10:
  531.  
  532. 1. Type the following string:
  533.  
  534.      "Hello again!"
  535.  
  536.                              - TUTORIAL 7.6 -
  537.  
  538. Note:
  539. The first character of "again!" is the 6th in the whole string
  540.  
  541. 2. Enter:
  542.  
  543.      6 +
  544.  
  545. Note:
  546. You have now added 6 to the address of the first character ("H") of the
  547. string.
  548.  
  549. 3.Finally, type:
  550.  
  551.      PUTS
  552.  
  553. and RPL replies
  554.  
  555.      again!
  556.  
  557. Some care is needed when using this "address arithmetic"; if you make an
  558. error and change the address so that it is outside of the original string
  559. data structure, then the results are quite unpredictable. In the worst
  560. case you could crash the system if you read from certain hardware
  561. registers by mistake.
  562.  
  563. 7.2.6 Stack Manipulation Words
  564.  
  565. There are a number of words that change the order of the stack items. The
  566. "SWAP" word, as it's name implies, takes two values off the stack top and
  567. puts them back in reverse order.
  568.  
  569. Example 11:
  570.  
  571.      1 5 SWAP
  572.  
  573.  after 1 after 5 after SWAP
  574.  
  575. +-------+-------+----------+
  576. |   1   |   5   |     1    |
  577. +-------+-------+----------+
  578.         |   1   |     5    |
  579.         +-------+----------+
  580.  
  581. "SWAP" is only needed if the order of the operands affects the result. It
  582. is unnecessary when using words such as "+" and "*" among others.
  583.  
  584. Quite often there is more than one way to enter an algebraic expression in
  585. RPL:
  586.  
  587. Example 12: Calculate the value of
  588.  
  589.      28 / (2 + 4 * 3)
  590.  
  591. 1. You start from within the parentheses as you would when calculating
  592.    manually:
  593.  
  594.      4 3 * 2 + 28 SWAP /
  595.  
  596.  after 4 after 3 after * after 2
  597.  
  598. +-------+-------+-------+-------+
  599. |  4    |   3   |   12  |   2   |
  600. +-------+-------+-------+-------+
  601.         |   4   |       |  12   |
  602.         +-------+       +-------+
  603.  
  604.  after + after 28 after SWAP after /
  605. +-------+--------+----------+-------+
  606. |  14   |   28   |    14    |   2   |
  607. +-------+--------+----------+-------+
  608.         |   14   |    28    |
  609.         +--------+----------+
  610.  
  611. 2. Or, start from the left:
  612.  
  613.      28 2 4 3 * + /
  614.  
  615.  after 28 2 4 3 after * after + after /
  616. +--------------+-------+-------+-------+
  617. |       3      |   12  |  14   |   2   |
  618. +--------------+-------+-------+-------+
  619. |       4      |   2   |  28   |
  620. +--------------+-------+-------+
  621. |       2      |   28  |
  622. +--------------+-------+
  623. |      28      |
  624. +--------------+
  625.  
  626. This illustrates that although you can usually manage without "SWAP", it
  627. can quite often make
  628.  
  629.                              - TUTORIAL 7.7 -
  630.  
  631. it easier to enter your expressions in an understandable way.
  632.  
  633. The next useful word for manipulating the stack, is "DUP"; which, as its
  634. name suggests, duplicates the top stack value. This is useful when you
  635. need an entered value or intermediate result more than once.
  636.  
  637. Example 13:
  638.  
  639. Calculate
  640.      (3 + 7 * 2) / 3 + (3 + 7 * 2) * 4.
  641.  
  642. You can convert it to RPL and get:
  643.  
  644.      3 7 2 * + 3/ 3 7 2 * + 4 * + .
  645.  
  646. or you can use DUP and get
  647.  
  648.      3 7 2 * + DUP 3 / SWAP 4 * + .
  649.  
  650. You can try these out and see for yourself that they give the same result.
  651.  
  652. To get a copy of the second stack item you use the word OVER.
  653.  
  654. Example 14:
  655.  
  656. To calculate 3 + 3 * 7 you can enter:
  657.  
  658.      3 7 OVER * + .
  659.  
  660. If you need get a copy of a value deeper in the stack you use the PICK
  661. word.
  662.  
  663. Example 15:
  664.  
  665. To get a copy of the fourth value on the stack you enter:
  666.  
  667.      4 PICK
  668.  
  669. Note:
  670. The count of stack items (i.e. 4) does not include the count itself
  671. although it will be on the stack top when "PICK" is applied. In the
  672. previous example 4 PICK will copy to the stack top the value which was the
  673. fourth stack item before 4 was entered.
  674.  
  675. "ROT" rotates the three topmost stack values so that the third item will
  676. become the top item, and the first and the second item (counting from the
  677. stack top) will be the second and the third stack item respectively.
  678.  
  679. Example 16: Push 3, 5 and 7 onto the stack and then apply ROT and see how
  680.             it changes the stack.
  681.  
  682.      3 5 7 ROT
  683.  
  684.  after 3 after 5 after 7 after ROT
  685. +-------+-------+-------+---------+
  686. |   3   |   5   |   7   |    3    |
  687. +-------+-------+-------+---------+
  688.         |   3   |   5   |    7    |
  689.         +-------+-------+---------+
  690.                 |   3   |    5    |
  691.                 +-------+---------+
  692.  
  693. Note:
  694. You can use the .S" word toprint the contents of the whole stack without
  695. removing any values to see how this example progresses.
  696.  
  697. The word ROLL is used to rotate a given number (n) of stack items so that
  698. the n'th stack item becomes the stack top item and all the items between
  699. the first and the n'th item are moved one position deeper in the stack.
  700.  
  701. Finally there is also a word for popping a value off the stack without
  702. printing it. The word is "DROP". You will need it later when you examine
  703. conditional execution.
  704.  
  705.                              - TUTORIAL 7.8 -
  706.  
  707. 7.2.7 Compiling New Words
  708.  
  709. The examples so far have only demonstrated that RPL can be used as a
  710. slightly peculiar calculator. If it is to be used as a programming
  711. language, RPL needs to be able to store a sequences of operations for
  712. repeated use or which need to be executed by another part of the program.
  713.  
  714. Many programming languages call these sequences functions or subroutines.
  715. The term "word" from the FORTH programming language is adopted for RPL.
  716.  
  717. A word is a collection of RPL code which can be recognised by its name.
  718. This code can consist of literals, references to variables and constants,
  719. and references to other words.
  720.  
  721. A definition of a word begins with a colon ":" continues with the name of
  722. the new word, and ends with a semicolon ";".
  723.  
  724. When the RPL interpreter scans the colon word, a new entry in the
  725. vocabulary is started. The name of the word and the type of entry (in
  726. this case a "word definition") are stored.
  727.  
  728. Everything between the name and the ending semicolon is compiled as the
  729. word's definition. When a previously defined word is given as part of the
  730. definition, a reference to it is stored. When a literal is given, its type
  731. (integer, float or string) and its value are stored in the entry. When a
  732. named constant or a variable (See: Constants and Variables) is given, a
  733. reference to its own entry is stored. In summary, the vocabulary entry for
  734. a word is made of a name, the word type and a set of literal values and
  735. references to previously defined words,
  736.  
  737. The following examples should help to explain:
  738.  
  739. Example 17: Define a word that prints out a specific string.
  740.  
  741. Enter:
  742.  
  743.      :Prompt
  744.       "PROMPT TEXT>" PUTS
  745.      ;
  746.  
  747. Remember, there has to be at least one space between ":" and the name for
  748. the new word, because the ":" is itself a word.
  749.  
  750. User-defined words are used just like any pre-defined word. To use them
  751. you just need to enter their name.
  752.  
  753. Example 17b: Use the word "Prompt" defined above.
  754.  
  755. Enter:
  756.  
  757.      Prompt
  758.  
  759. RPL will print:
  760.  
  761.      PROMPT_TEXT>
  762.  
  763. User defined words would be quite useless if you couldn't pass information
  764. to them to control their operation. However, as mentioned above, user-
  765. defined words are indistinguishable from the built-in words. This means
  766. that passing operands to them is carried out using the Parameter Stack in
  767. exactly the same way as you have passed operands to words since Example 1!
  768.  
  769. Now test this by defining your own interger printing word.
  770.  
  771. Example 18: New integer printing word.
  772.  
  773.      : MyPrint
  774.       .
  775.      ;
  776.  
  777.                              - TUTORIAL 7.9 -
  778.  
  779. Call it:
  780.  
  781.      10 MyPrint
  782.  
  783. and RPL responds:
  784.  
  785.      10
  786.  
  787. Or call it as follows:
  788.  
  789.      10 20 100 MyPrint MyPrint MyPrint
  790.  
  791. and the reply will be:
  792.  
  793.      100 20 10
  794.  
  795. Now create a function which prints numbers out twice. To do this, you have
  796. to use the "DUP" word mentioned previously.
  797.  
  798. Example 19: Print number twice as an integer.
  799.  
  800.      : My2Print
  801.       DUP
  802.       .
  803.       .
  804.      ;
  805.  
  806. Now call it:
  807.  
  808.      10 My2Print
  809.  
  810. and it will reply:
  811.  
  812.      10 10
  813.  
  814. or if you call it as follows:
  815.  
  816.      10 My2Print 20 My2Print 100 My2Print
  817.  
  818. RPL responds with:
  819.  
  820.      10 10 20 20 100 100
  821.  
  822. Before the final example in this section you should learn how to use
  823. "comments" so you can add notes to your program to inform others how it
  824. works (or remind yourself at a later date). The word "(" tells RPL to skip
  825. all following text up to the next ")" command or until the end of the
  826. current line. Because "(" is a word, you have to separate it from the text
  827. that follows with a space.
  828.  
  829. Comment Examples:
  830.  
  831.      1.
  832.      ( this is a comment )
  833.  
  834.      2.
  835.      ( these are also
  836.      ( legal comments
  837.  
  838.      3.
  839.      (this produces syntax error)
  840.  
  841.      4.
  842.      ( this is an illegal comment too )
  843.  
  844. Finally create a function, which takes three numbers as an input and
  845. returns the integer average of them,
  846.  
  847. Example 20: Calculate the average of three numbers.
  848.  
  849.      : MyAver
  850.       ( add 3 numbers and divide result by 3 )
  851.       + + 3/
  852.      ;
  853.  
  854. If you call it as follows:
  855.  
  856.      10 20 30 MyAver .
  857.  
  858. RPL returns:
  859.  
  860.      20
  861.  
  862. or try:
  863.  
  864.      10 20 120 MyAver .
  865.  
  866. and the response will be:
  867.  
  868.      50
  869.  
  870.                              - TUTORIAL 7.10 -
  871.  
  872. 7.2.8 Constants and Variables
  873.  
  874. RPL has a mechanism to store and fetch values not only from the stack but
  875. also in "constants" and "variables". A "constant" is a named entity whose
  876. value is set when it is defined, and the value can be referenced but not
  877. changed. A "variable" is a named entity whose value can be referenced and
  878. used for either input or output.
  879.  
  880. Constants and variables must be defined outside word definitions. When a
  881. constant is defined, its value is taken from the stack top. When you later
  882. want to reference a constant you enter its name.
  883.  
  884. 7.2.8.1 Constants
  885.  
  886. Constants are used for storing values that won't change. Although this
  887. might seem to be the same as using literals, it is good programming
  888. practice to use constants instead of literal values. Constants should be
  889. descriptive, and this makes your code much easier to read by others as
  890. well as yourself. When a constant is referrenced by its name, the value
  891. is placed on the stack.
  892.  
  893. Example 21 : Define integer constant "DaysInAWeek" with the value 7.
  894.  
  895. Enter:
  896.  
  897.      7 CONSTANT DayslnAWeek
  898.  
  899. Then entering:
  900.  
  901.      DaysInAWeek .
  902.  
  903. prints out:
  904.  
  905.      7
  906.  
  907. Example 22: Define the value for the floating-point constant "PI".
  908.  
  909.      3.14159 FCONSTANT PI
  910.  
  911. 7.2.8.2 Variables
  912.  
  913. When a numeric variable is defined, its initial value is set to zero. For
  914. each numeric type (integer and floating-point) there are two words that
  915. are used to access this value.
  916.  
  917. For integer variables these words are:
  918.  
  919. @ (fetch) - takes the address of an integer variable and returns the value
  920.   of that variable on the stack.
  921.  
  922. ! (store) - takes two operands: the address of the integer variable and
  923.   the new value for the variable, and changes the value of the variable.
  924.   The address must be the top item on the stack and the new value the
  925.   second.
  926.  
  927. The address of a variable is pushed onto the stack when it is referred to,
  928. not the value as with constants.
  929.  
  930. Example 23: Define integer variable COUNTER and store 17 into it, then
  931.             check its value.
  932.  
  933.      VARIABLE counter
  934.      17 counter !
  935.      counter @ .
  936.  
  937. Examine what happened during this example step by step:
  938.  
  939.      "VARIABLE counter"
  940.  
  941. 1. Space was reserved for one integer value, to be accessed by the name
  942.    "counter".
  943.  
  944.      "17 counter !"
  945.  
  946. 2. The number 17 was pushed onto the stack.
  947.  
  948.                              - TUTORIAL 7.11 -
  949.  
  950. 3. The address of the variable was fetched and pushed onto the stack.
  951.  
  952. 4. The word "!" was executed, which takes the address of a variable off
  953.    the stack and assigns the second operand to the value at that address.
  954.    In a way, the name of a variable is the address of its value.
  955.  
  956.      "counter @ ."
  957.  
  958. 5. The address of the "counter" variable was again pushed onto the stack.
  959.  
  960. 6. The word "@" was executed, which moves the contents from the given
  961.    address onto the stack.
  962.  
  963. 7. The "." word was executed, which printed the value from the stack to
  964.    your window.
  965.  
  966. There are corresponding words for floating-point variables; which are
  967. "FVARIABLE", "F!" and "F@".
  968.  
  969. Variables and constants can be used inside or outside of a word
  970. definition. When used inside a word definition, only a reference to the
  971. constant or variable is compiled in the word's dictionary entry.
  972.  
  973. The value of the constant or the address of the variable is fetched only
  974. when the word is executed, not when it is defined.
  975.  
  976. Although the stack is object oriented and can automatically convert
  977. between numeric types, the internal storage of integer and floating-
  978. point variables is different. This means that words that operate on
  979. floating-point variables, i.e. F! and F@ should not be used to access
  980. integer variables. The same applies to floating-point variables and the
  981. words for integer variable access (! and @).
  982.  
  983. 7.2.9 Flow Control
  984.  
  985. Every programming language has to be able to alter the program flow when
  986. certain conditions are met. It is also necessary to be able to repeatably
  987. execute a section of code. RPL has addressed these needs by including a
  988. versatile set of words into its basic vocabulary for controlling program
  989. flow. The flow control words can only be used from within word
  990. definitions.
  991.  
  992. 7.2.10 Conditional Execution
  993.  
  994. It is often necessary to decide whether a section of code should be
  995. executed or not. This is called conditional execution . The most basic
  996. conditional execution structure is "IF..ENDIF".
  997.  
  998. The "IF" word takes the stack top value and uses it to make a decision
  999. about how the execution is to proceed; this decision value is called a
  1000. "flag". In RPL a flag value is said to be "FALSE" if it is equal to zero
  1001. and "TRUE" if it has any other value. If the flag is TRUE, the words
  1002. between IF and the corresponding ENDIF are executed, otherwise execution
  1003. skips to the word that is immediately after the ENDIF.
  1004.  
  1005. 7.2.10.1 Comparisons
  1006.  
  1007. To put a flag on the stack ready for IF, it is useful to use words that
  1008. compare stack items and as a result push a flag on the stack. Built into
  1009. RPL are the following comparison words:
  1010.  
  1011. Integer  Float
  1012. ----------------------------
  1013. =        F=       - is equal
  1014. <        F<       - is less
  1015. >        F<       - is greater
  1016. >=       F>=      - greater or equal
  1017. <=       F<=      - less or equal
  1018. <>       F<>      - not equal
  1019.  
  1020. Each of these takes two stack values, compares them, and places a flag
  1021. onto the stack whose value depends upon the result of the comparison.
  1022.  
  1023.                              - TUTORIAL 7.12 -
  1024.  
  1025. Example 24: Compare 2 and 3 to see which is less.
  1026.  
  1027.      2 3 <
  1028.  
  1029. The second stack item is compared to the first stack item; the flag pushed
  1030. on the stack indicates whether 2 is less than 3. A value of 1 means
  1031. "TRUE", and a 0 means "FALSE".
  1032.  
  1033.  after 2 after 3 after <
  1034. +-------+-------+-------+
  1035. |   2   |   3   |   1   |
  1036. +-------+-------+-------+
  1037.         |   2   |
  1038.         +-------+
  1039.  
  1040. The flag states that two is less than three (as you may have guessed).
  1041.  
  1042. 7.2.10.2 IF..ENDIF Structure
  1043.  
  1044. This is the simplest form of conditional execution structure.
  1045.  
  1046. Example 25: Unpredictable program execution
  1047.  
  1048.      : Maybe
  1049.       RANDOM 0.5 F<
  1050.       IF
  1051.         "Yes," PUTS
  1052.       ENDIF
  1053.       "Thats it" PUTS
  1054.      ;
  1055.  
  1056. Try executing "Maybe" several times and examine its response.
  1057.  
  1058. Note:
  1059. This introduces the word "RANDOM" which returns a random floating-
  1060. point number between 0.0 and 1.0 when executed.
  1061.  
  1062. The previous example tests whether the return value from "RANDOM" is less
  1063. than 0.5. If it is, it prints out the text "Yes, Thats it" otherwise it
  1064. just prints "Thats it".
  1065.  
  1066. This is the explanation of the previous example. When the "Maybe" is
  1067. executed:
  1068.  
  1069. 1. Executing "RANDOM" pushes a floating-point value onto the stack
  1070.  
  1071. 2. 0.5 is pushed onto the stack
  1072.  
  1073. 3. The "F<" word takes two (floating-point) operands, compares
  1074.    "random<0.5" and pushes the flag back onto the stack.
  1075.  
  1076. 4. The "IF" function takes the flag off the stack and if it is non-zero,
  1077.    then the ""Yes," PUTS"" text is executed; otherwise execution skips to
  1078.    ""Thats it" PUTS"" after the "ENDIF".
  1079.  
  1080. Note:
  1081. That "IF" and "ENDIF" words must be contained within a word definition;
  1082. also that every "IF" needs one corresponding "ENDIF".
  1083.  
  1084. 7.2.10.3 IF..ELSE..ENDIF Structure
  1085.  
  1086. Now you can define a word that prints only positive values, negative
  1087. values are just disposed of.
  1088.  
  1089. Example 26: Word to print only positive values.
  1090.  
  1091.      : .Pos
  1092.       DUP 0> ( compare operand to zero )
  1093.       IF
  1094.         . ( print it if greater )
  1095.       ENDIF
  1096.      ;
  1097.  
  1098. If you enter:
  1099.  
  1100.      4 .Pos
  1101.  
  1102. RPL returns:
  1103.  
  1104.      4
  1105.  
  1106. So that seems to work.
  1107.  
  1108. But what happens if you enter:
  1109.  
  1110.                              - TUTORIAL 7.13 -
  1111.  
  1112.      -2 4 3 -1 .Pos .Pos .Pos .Pos
  1113.  
  1114. It doesn't produce:
  1115.  
  1116.                                     3 4
  1117.  
  1118. but nothing at all. The problem is that the word does not get rid of the
  1119. negative values, so you called .Pos four times with the same value of -1
  1120. on the stack.
  1121.  
  1122. You need to take some action if the value on the stack is not greater than
  1123. zero. This is handled using an "ELSE" branch where the negative value will
  1124. be dropped off the stack.
  1125.  
  1126. Example 26b: Correct way to print only positive values.
  1127.  
  1128.      : .Pos
  1129.       DUP 0 >
  1130.       IF
  1131.         .
  1132.       ELSE
  1133.         DROP
  1134.       ENDIF
  1135.      ;
  1136.  
  1137. This demonstrates another form of the IF structure, the IF. .ELSE..ENDIF
  1138. structure.
  1139.  
  1140. If you now enter
  1141.  
  1142.      -2 4 3 -1 .Pos .Pos .Pos .Pos
  1143.  
  1144. you get
  1145.  
  1146.      3 4
  1147.  
  1148. as originally intended.
  1149.  
  1150. 7.2.10.4 Inverting Flags
  1151.  
  1152. As well as the integer and floating-point comparison words, there is one
  1153. other useful word for use in conditional structures.The "NOT" word can
  1154. be used for reversing the result of a comparison.
  1155.  
  1156. For example:
  1157.  
  1158.      1 0 20 <> .
  1159.  
  1160. and:
  1161.  
  1162.      10 20 = NOT .
  1163.  
  1164. Both print out the same value of "1" because the condition is TRUE.
  1165.  
  1166. 7.2.10.5 Nesting Conditionals
  1167.  
  1168. Conditional structures can also be nested. This means that they can be
  1169. stacked inside each other providing that for each "IF" of "IF..ELSE" there
  1170. is a corresponding "ENDIF".
  1171.  
  1172. Example 27: Use of nested IF..ELSE..ENDIF structure.
  1173.  
  1174.      : CheckIt
  1175.       DUP ( duplicate the operand so that you don't lose it
  1176.       0 = ( compare it against to zero )
  1177.       IF
  1178.         "Zero" PUTS
  1179.         DROP ( dispose of duplicate because it won't be needed
  1180.      ELSE
  1181.         0 > ( make comparison "is greater than" with duplicate
  1182.         IF
  1183.            "Greater" PUTS
  1184.         ELSE
  1185.            "Less " PUTS
  1186.         ENDIF
  1187.       ENDIF
  1188.      ;
  1189.  
  1190.                              - TUTORIAL 7.14 -
  1191.  
  1192.  
  1193.  
  1194.  
  1195. Now call it as follows:
  1196.  
  1197.      -2 CheckIt
  1198.      3.7 CheckIt
  1199.      0 CheckIt
  1200.  
  1201. you should get the following response:
  1202.  
  1203.      Less
  1204.      Greater
  1205.      Zero
  1206.  
  1207. 7.2.11 Loops
  1208.  
  1209. In this section, the RPL words for branching back to repeat sections of
  1210. code several times will be explained. This type of control structure is
  1211. called a "loop". There are two basic kinds of loop: definite loops, which
  1212. execute a specific number of times unless interupted, and indefinite
  1213. loops, whose repeated execution is controlled conditionally in much the
  1214. same way as the IF..ENDIF structure.
  1215.  
  1216. 7.2.11.1 Definite Loops
  1217.  
  1218. The basic RPL control structure for executing definite loops is
  1219. "DO..LOOP". You specify beginning and ending values, called the limits,
  1220. for a "loop variable". The ending value is first pushed onto the stack,
  1221. then the beginning value, before the word "DO". Then you put the words to
  1222. be repeated, and the structure ends with the word "LOOP".
  1223.  
  1224. Example 28: Printing a string 1 00 times.
  1225.  
  1226.      : DoLoop
  1227.       100 0 DO
  1228.         "RPL loops in style!" PUTS
  1229.       LOOP
  1230.      ;
  1231.      DoLoop
  1232.  
  1233. The "loop variable", or index, starts with the starting value, and is
  1234. incremented by 1 at the end of each iteration of the loop. When it reaches
  1235. the ending value the loop is exited. There is a word for retrieving the
  1236. value of the index. Its name is "I", and it should only be used between
  1237. "DO" and "LOOP". It puts the current value of the loop variables on the
  1238. stack.
  1239.  
  1240. Example 29: Count up from 1 to 9 and print the index.
  1241.  
  1242.      : OneToNine
  1243.       10 1 DO
  1244.         I.
  1245.       LOOP
  1246.      ;
  1247.  
  1248.      OneToNine
  1249.  
  1250. Prints:
  1251.  
  1252.      1 2 3 4 5 6 7 8 9
  1253.  
  1254. The "DO..LOOP" always starts at a value and counts up by one until it
  1255. reaches the ending value. If you want to increment the index by a value
  1256. other than 1 , you can use another form of the definite loop: the
  1257. "DO..+LOOP". The "+LOOP" word takes an operand from the stack and adds
  1258. it to the index.
  1259.  
  1260. If the ending value is greater than the beginning value, then the loop is
  1261. exited if the loop variable becomes greater than or equal to the ending
  1262. value.
  1263.  
  1264. Example 30: Count from 0 to 1 0 in twos, printing the index.
  1265.  
  1266.      : UpInTwos
  1267.       10 0 DO
  1268.         I.
  1269.       2+LOOP
  1270.      ;
  1271.  
  1272.      UpInTwos
  1273.  
  1274. Prints:
  1275.  
  1276.      0 2 4 6 8
  1277.  
  1278.                              - TUTORIAL 7.15 -
  1279.  
  1280. If the ending value is less than the beginning value, then the
  1281. "DO..+LOOP" is exited when the loop variable becomes less than or equal
  1282. to the ending value.
  1283.  
  1284. Example 31: Count down by one and print the index.
  1285.  
  1286.      : DownByOnes
  1287.       10 0 DO
  1288.         I.
  1289.       -1 +LOOP
  1290.      ;
  1291.  
  1292.      0 5 DownByOnes
  1293.  
  1294. Prints:
  1295.  
  1296.      5 4 3 2 1
  1297.  
  1298. Note:
  1299. In this example the word "DownByOnes" takes its operands from the stack,
  1300. so you must supply them when you call the word.
  1301.  
  1302. Both forms of the "DO" loop execute at least once since the conditional
  1303. check is made when "LOOP" or "+LOOP" is executed. It is possible to
  1304. terminate a definite loop prematurely. The execution of word "LEAVE"
  1305. causes the loop to terminate at the next "LOOP" or "+LOOP".
  1306.  
  1307. Example 32: Print the squares of numbers until the square > 50.
  1308.  
  1309.      : SquareLoop
  1310.       10 0 DO
  1311.         I DUP * ( square index )
  1312.         DUP
  1313.         50 > IF ( compare the square to 50 )
  1314.           DROP
  1315.           LEAVE
  1316.         ELSE
  1317.           .
  1318.         ENDIF
  1319.       LOOP
  1320.      ;
  1321.  
  1322. When execute "SquareLoop" will print the squares of I until they exceed
  1323. 50.
  1324.  
  1325. 7.2.11.2 Indefinite Loops
  1326.  
  1327. Unlike definite loops, an indefinite loop does not terminate after a
  1328. specified number of iterations. It terminates when a condition is met,
  1329. if ever.
  1330.  
  1331. All indefinite loops, just like definite loops, must lie entirely within
  1332. a single definition. The structure of the indefinite loops are:
  1333.  
  1334.      BEGIN..UNTIL
  1335.  
  1336.      BEGIN..WHILE..REPEAT
  1337.  
  1338.      BEGIN..AGAIN
  1339.  
  1340. In each of these loops, "BEGIN" marks the beginning of the loop body,
  1341. which extends to the terminating word "UNTIL" , "REPEAT", or "AGAIN".
  1342.  
  1343. In the "BEGIN. .UNTIL" loop a flag is tested and removed from the stack at
  1344. the end of each repetition of the loop. If the flag is TRUE, the loop
  1345. terminates. Otherwise the loop repeats from the first word following
  1346. "BEGIN". Since the test is made at the end of the loop, the loop will
  1347. always be executed at least once.
  1348.  
  1349. Example 33:
  1350.  
  1351.      : CountDown 1
  1352.       BEGIN
  1353.         DUP . ( print it out )
  1354.         1 - ( decrement by one )
  1355.         DUP 0 <= ( if TRUE, terminate loop )
  1356.       UNTIL
  1357.       DROP
  1358.       "PANG" PUTS
  1359.      ;
  1360.  
  1361.      10 CountDown1
  1362.  
  1363. The "BEGIN..WHILE..REPEAT" form of indefinite loop first executes the
  1364. code between "BEGIN" and "WHILE", and then a flag is tested, If the flag
  1365. is TRUE, the words between "WHILE" and "REPEAT" are executed; then
  1366. execution returns to "WHILE". If the flag is FALSE, then execution skips
  1367. to after the "REPEAT".
  1368.  
  1369.                              - TUTORIAL 7.16 -
  1370.  
  1371. Example 34: 
  1372.  
  1373.      : CountDown2
  1374.  
  1375.       BEGIN
  1376.         1 - ( decrement by one )
  1377.         DUP ( if 0, terminates the loop )
  1378.       WHILE
  1379.         DUP .
  1380.       REPEAT
  1381.  
  1382.      "Bang" PUTS
  1383.       DROP
  1384.      ;
  1385.  
  1386.      10 CountDown2
  1387.  
  1388. The third form of indefinite loop has the form "BEGIN..AGAIN". Which
  1389. executes forever unless either the word "QUIT" or "EXIT" is executed.
  1390.  
  1391. "QUIT" terminates execution, empties all stacks and returns control to the
  1392. interpreter, while "EXIT" exits the current word.
  1393.  
  1394. Example 35:
  1395.  
  1396.      : CountDown3
  1397.       BEGIN
  1398.         DUP .
  1399.         1 -
  1400.         DUP NOT
  1401.         IF
  1402.           EXIT
  1403.         ENDIF
  1404.       AGAIN
  1405.      ;
  1406.  
  1407.      10 CountDown3
  1408.  
  1409. 7.2.11.3 Nested Loops
  1410.  
  1411. As with conditional structures, all the loop forms can be nested, In
  1412. Examples 29 to 32 you used the RPL word "I" to obtain the value of the
  1413. loop variable; when you nest "DO. .LOOP" structures the words "J" and "K"
  1414. can be used to copy the indices of the second and third outer loops,
  1415. respectively.
  1416.  
  1417. Example 36: Print a multiplication table.
  1418.  
  1419.      ( print carriage return and line feed: )
  1420.      : CR 13 EMIT 10 EMIT .
  1421.  
  1422.      : multTable
  1423.       6 1 DO
  1424.       11 1 DO
  1425.         I J * ( multiply indices
  1426.           .   ( and print the product
  1427.         LOOP
  1428.         CR
  1429.       LOOP
  1430.      ;
  1431.  
  1432.      multTable
  1433.  
  1434. Will print:
  1435.  
  1436.      1 2 3 4 5 6 7 8 9 10
  1437.      2 4 6 8 10 12 14 16 18 20
  1438.      3 6 9 12 15 18 21 24 27 30
  1439.      4 8 12 16 20 24 28 32 36 40
  1440.      5 10 15 20 25 30 35 40 45 50
  1441.  
  1442. This looks a little untidy so you can tidy it up by adding a conditional
  1443. to print a space.
  1444.  
  1445. Example 36b: Print a neat multiplication table.
  1446.  
  1447.      : multTable
  1448.       6 1
  1449.       DO
  1450.         11 1
  1451.         DO
  1452.           I J * ( multiply indices
  1453.           DUP   ( duplicate product for testing
  1454.           10 <
  1455.           IF    ( if<10 then print a space first
  1456.             "" PUTS
  1457.             .   ( now print product
  1458.           ELSE  ( two digits in product
  1459.             .   ( so just print it
  1460.           ENDIF
  1461.         LOOP
  1462.         CR
  1463.       LOOP
  1464.      ;
  1465.  
  1466.      multTable
  1467.  
  1468.                              - TUTORIAL 7.17 -
  1469.  
  1470. Note:
  1471. It is a convention to indent flow control structures as shown in the
  1472. previous two examples. This does not make any difference to the RPL system
  1473. but, like comments, makes your programs easier to read and understand.
  1474.  
  1475. 7.2.12 Words and the Vocabulary
  1476.  
  1477. The last example, as well as being your most comprehensive RPL program to
  1478. date also demonstrates an important feature of the RPL language. If you
  1479. define a word with the same name as a previously defined word then the
  1480. latest definition is used.
  1481.  
  1482. You can list the whole vocabulary of your current RPL window by entering
  1483. the word "VLIST". Before you do this use the size gadget of the window to
  1484. make it a decent size, the vocabulary is quite long.
  1485.  
  1486. The whole vocabulary, including the built-in words, will be printed to the
  1487. RPL window in chronological order with the latest words printed first. You
  1488. should see that the last two words are both "mult_table".
  1489.  
  1490. It is possible to remove word definitions from the vocabulary using the
  1491. word "FORGET".
  1492.  
  1493. Example 37 : Remove neat "multTable" from vocabulary.
  1494.  
  1495.      FORGET mult_table
  1496.  
  1497. If you now execute "multTable" you will get the original untidy version.
  1498.  
  1499. "FORGET" actually removes ALL the words after the specified word. So,
  1500. assuming you have worked through all the examples, if you enter:
  1501.  
  1502.      FORGET Prompt
  1503.  
  1504. Then all the words you have defined during this tutorial will be deleted.
  1505. It is important to note that the RPL system makes NO DISTINCTION between
  1506. the built-in words and words defined interactively or by loading a file
  1507. (see next section). This means that if you create a word definition using
  1508. the name of one of the built-in words then your new definition will
  1509. replace the original. This can be quite significant if you replace an
  1510. important or frequently used word.
  1511.  
  1512. You can of course recover the situation using "FORGET"; which raises
  1513. another important point: you can delete built-in words just as easily as
  1514. your own. This makes it possible to create a situation where RPL does not
  1515. have the vocabulary to do anything! Closing the window and opening a new
  1516. one enables you to start with a fresh RPL environment.
  1517.  
  1518. 7.2.13 Loading a File
  1519.  
  1520. Entering RPL definitions directly to the window is acceptable for the
  1521. short examples so far in this tutorial, but it is hard to recover from
  1522. mistakes without having to completely re-enter a definition. Using a text
  1523. editor you can write any RPL code to a file and then load that file into
  1524. your RPL window.
  1525.  
  1526. Example 38:
  1527.  
  1528. Write the following RPL program using your favourite text editor and save
  1529. it as "ram:test.rpl"
  1530.  
  1531.      "loading..." PUTS
  1532.  
  1533.      : CR
  1534.       13 EMIT 10 EMIT
  1535.      ;
  1536.  
  1537.      : Hello
  1538.       "Hello world" PUTS CR
  1539.      ;
  1540.  
  1541.      "Done" CR
  1542.  
  1543.                              - TUTORIAL 7.18 -
  1544.  
  1545. Now type the following program:
  1546.  
  1547.      "ram:test.rpl" LOAD
  1548.  
  1549. RPL responds:
  1550.  
  1551.      loading ... Done
  1552.  
  1553. Now the words CR and Hello are defined and you can call them. Type:
  1554.  
  1555.      Hello
  1556.  
  1557. and RPL responds
  1558.  
  1559.      Hello world
  1560.  
  1561. 7.2.14 Using RPL windows
  1562.  
  1563. You open a RPL window by selecting PROJECT/Windows/RPL. You can have many
  1564. RPL windows if you want. RPL windows are similar to OS "Shell" windows.
  1565. You can use <RAM>C and <RAM>V to cut and paste text to and from the
  1566. "clipboard" and the cursor keys can be used to edit your text and even
  1567. fetch previously entered text from the window "history" buffer.
  1568.  
  1569. Each window is separate so that whatever words are defined in one window,
  1570. cannot be used in other windows. Of course you can define identical words
  1571. in different windows. The stacks are also specific to each window.
  1572.  
  1573. It is possible though to use words defined in another window by
  1574. establishing a parent-child link between two windows. This is done
  1575. using the word INHERIT . The syntax for this word is:
  1576.  
  1577.      "name_of_RPL_window" INHERIT
  1578.  
  1579. Example 39:
  1580.  
  1581. 1. Define a word "HiThere" in your current RPL window
  1582.  
  1583.      : HiThere
  1584.       "Hi There" PUTS
  1585.      ;
  1586.  
  1587. 2. Open a new RPL window and try to execute the word "HiThere":
  1588.  
  1589.      HiThere
  1590.  
  1591. RPL responds
  1592.  
  1593.      HiThere ?
  1594.  
  1595. because it didn't recognize the word.
  1596.  
  1597. 3. Now enter the following line:
  1598.  
  1599.      "RPL" INHERIT
  1600.  
  1601. 4. Try HiThere again and RPL responds "Hi There"
  1602.  
  1603. From now on interactive commands, as well as new definitions entered in
  1604. the "RPL.1" window search the vocabulary of "RPL.1", and then, if the word
  1605. is not found, the vocabulary of "RPL". So if you have defined identical
  1606. words in both windows the definition in "RPL.1" will take priority.
  1607.  
  1608. Note:
  1609. The INHERIT word actually takes an address as its operand, and this
  1610. address points to the string containing the name of the RPL window whose
  1611. vocabulary you wish to INHERIT Remember by entering the string between the
  1612. double-quote marks its address was pushed onto the stack as an operand.
  1613.  
  1614.                              - TUTORIAL 7.19 -
  1615.  
  1616. 7.3 USING RPL FOR CUSTOMIZING EDITOR
  1617.  
  1618. In this section we will show you how to use RPL to customize and expand
  1619. the user interface and functionality of REAL 3D.
  1620.  
  1621. The real power behind the customization is based on the fact that
  1622. customization allows persons to develop working environments which suit
  1623. as well as possible their different modelling needs, styles, and tools.
  1624. Other people can take advantage of these additional tools etc developed
  1625. by somebody else.
  1626.  
  1627. 7.3.1 Communicating with RPL Programs
  1628.  
  1629. Before we can go any further, let's take a look how RPL programs can
  1630. interact with the user and vice versa.
  1631.  
  1632. RPL contains sets of words which can be used for requesting information
  1633. from the user.
  1634.  
  1635. Open one View window and write the following program:
  1636.  
  1637.      : AreYouSure
  1638.       "YeslNo" "Are You Sure?" GET_ KEY
  1639.       IF
  1640.         "You are sure" PUTS
  1641.       ELSE
  1642.         "You are not sure" PUTS
  1643.       ENDIF
  1644.      ;
  1645.  
  1646.      AreYouSure
  1647.  
  1648. When you call the word by typing its name, REAL 3D opens a requester with
  1649. the header text "Are You Sure". Depending on which gadget you click RPL
  1650. prints out either the text "You are sure" or "You are not sure". So, the
  1651. word GET KEY takes two parameters: a string defining gadgets to be created
  1652. and the header text for the requester. It returns a value corresponding
  1653. to the selected gadget. Gadgets are separated with the character "l" and
  1654. it is possible to create any number of them (well, there should be at
  1655. least one).
  1656.  
  1657. Write the following program:
  1658.  
  1659.      : GetKeyTest
  1660.       "FirstlSecondlThirdlCancel"
  1661.       "Select One of These" GET_KEY
  1662.       .
  1663.      ;
  1664.  
  1665. Now call the word GetKeyTest several times and see what values it returns.
  1666. The value corresponding to the rightmost gadget is always 0 (right
  1667. selection is used for negative choice, hence the value 0). The value
  1668. corresponding to the leftmost gadget corresponds to the value of 1 and is
  1669. incremented gadget by gadget from left to right.
  1670.  
  1671. The word GET STR can be used for requesting strings from the user, such as
  1672. object names. It takes three parameters: the address of the buffer to hold
  1673. the string, the maximum length for the string and the header text for the
  1674. requester.
  1675.  
  1676. Write the following program:
  1677.  
  1678.      16 STRING ObjName
  1679.  
  1680.      : ObjCreate
  1681.       ObjName 1 5 "Create Object" GET _STR
  1682.       IF
  1683.         wOT_OR ObjName "CEND" C_LEVEL DROP
  1684.       ENDIF
  1685.      ;
  1686.  
  1687.      ObjCreate
  1688.  
  1689.      /*
  1690.      Get string from the user
  1691.      */
  1692.  
  1693.                              - TUTORIAL 7.20 -
  1694.  
  1695. This word opens a requester which allows you to enter the name for the
  1696. object. If you select the gadget OK, the word creates a level object with
  1697. the name you defined.
  1698.  
  1699. The word GET_FLT allows you to request numerical data from the user. It
  1700. takes two parameters: the address of the buffer (variable) to hold the
  1701. defined value and a title for the requester.
  1702.  
  1703. For example:
  1704.  
  1705.      FVARIABLE Length
  1706.  
  1707.      : GetLen
  1708.       Length "Define Length" GET_FLT
  1709.       IF
  1710.         Length F@ F.
  1711.       ENDIF
  1712.      ;
  1713.  
  1714.      GetLen
  1715.  
  1716. This program asks user to define "Length" and prints it out.
  1717.  
  1718. Its time to leave these "user interface" words now. There are also words
  1719. available for requesting file names and vectors etc. These words can be
  1720. used in a pretty similar way to those we have already discussed. Consult
  1721. the "Reference Manual" whenever you need to use them.
  1722.  
  1723. 7.3.2 "Master" ENVIRONMENT
  1724.  
  1725. When R3D2 is first started one RPL environment is created. Unlike RPL
  1726. windows this has no window associated with it.
  1727.  
  1728. "Master" environment is responsible for taking care of the following
  1729. things:
  1730.  
  1731. 1. Processing of AREXX commands. All ARexx commands arriving to ARexx
  1732.    port of REAL 3D are directly passed to RPL interpreter.
  1733.  
  1734. 2. Executing MACROS. For example, whenever you select the menu Project/
  1735.    Macros/Execute_Current, the following program is passed to Masters
  1736.    RPL environment:
  1737.  
  1738.      "t:macro.rpl" LOAD
  1739.  
  1740. 3. Processing key bindings. When you press any key, that key with the
  1741.    prefix "KEY_" is passed to Masters RPL interpreter. For example, when
  1742.    you press the key "k", then the RPL word "KEY_k" attempts to execute.
  1743.    If such a word cannot be found, the display is flashed as an error
  1744.    indicator.
  1745.  
  1746. 4. Processing RPL programs bound to icons in the Tool windows.
  1747.  
  1748. 7.3.3 Binding Macros to Keys
  1749.  
  1750. Any RPL program can be bound to any key by defining a word which has the
  1751. same name as the key in question with the prefix KEY_. The word must be
  1752. defined in Master's RPL Environment and it must return information with
  1753. which windows should be refreshed. This return value consists of flags
  1754. corresponding to each window type. Constants for these are defined in the
  1755. file "editor.rpl".
  1756.  
  1757.      IWR_SELECT
  1758.      IWR_VIEW
  1759.      IWR_MAT
  1760.      IWR_ANIM
  1761.      IWR_COL
  1762.      IWR_ALL
  1763.  
  1764. How to define words to "Masters" environment? There are three possible
  1765. ways to do it:
  1766.  
  1767. 1. Write a RPL program using any text editor, save it to a file and
  1768.    execute that file as a Macro.
  1769.  
  1770. 2. Insert your RPL program to the file "s:rpl-startup".
  1771.  
  1772.                              - TUTORIAL 7.21 -
  1773.  
  1774. 3. Send your RPL program to ARexx port of REAL 3D.
  1775.  
  1776. Let's write a simple RPL program and bind it to a key.
  1777.  
  1778. 1. Add the following RPL program to the end of the file "s:rpl-startup".
  1779.  
  1780.      : KEY +
  1781.       1 O_LOCK ( lock object data exclusively
  1782.                ( fetch selected objects on the stack:
  1783.       O_GETSEL
  1784.       0.1 0 0 0 M_MOVE
  1785.       0 O_LOCK (free lock
  1786.       IWR_VIEW ( only View must be refreshed
  1787.      ;
  1788.  
  1789. 2. Start REAL 3D and create some objects.
  1790.  
  1791. 3. Select one of the created objects and press the key "+". This causes
  1792.    "Master" to call your KEY + word which moves the selected objects to
  1793.    the positive direction of "x" axis.
  1794.  
  1795. Of course this is very stupid thing to do. So, let's improve it by asking
  1796. the user how much the selected objects should be moved.
  1797.  
  1798. 1. Exit the Real and load s:rpl-startup file to your text editor.
  1799.  
  1800. 2. Modify the KEY + word so that it looks like the following one:
  1801.  
  1802.      "vectors. rpl" LOAD
  1803.      VVARIABLE vMovement
  1804.  
  1805.      : KEY +
  1806.       vMovement "Move Selected Object"
  1807.       GET_VECT
  1808.       IF
  1809.         1 O_LOCK
  1810.         O_GETSEL
  1811.         V@ vMovement 0 M_MOVE
  1812.         0 O_LOCK
  1813.       ENDIF
  1814.       IWR_VIEW
  1815.      ;
  1816.  
  1817. Now, start Real, create some objects, and press the key "+". REAL 3D opens
  1818. a requester which allows you to enter three values defining how much to
  1819. move selected objects. If you exit the requester with OK, all selected
  1820. objects will be moved.
  1821.  
  1822. Note:
  1823. As a matter of fact, this is very handy macro because the requester allows
  1824. you to define the formulas which are then automaticaly evaluated.
  1825.  
  1826. 1. Press the key "+".
  1827.  
  1828. 2. Type the following formula to the first gadget:
  1829.  
  1830.      10*3.14/100
  1831.  
  1832. and press the enter key. Your formula is evaluated and replaced with the
  1833. result:
  1834.  
  1835.      0.314
  1836.  
  1837. 3. Click OK and the macro moves all selected objects 0.314 units along
  1838.    the "x" axis.
  1839.  
  1840. One very powerful feature provided by REAL 3D is ability to open several
  1841. screens. For example, you can use one HAM screen for rendering images and
  1842. another four color hires screen for modelling. The following macro tries
  1843. to bring the "Palette" window to the front, and if there are no Palette
  1844. windows, it opens one. This kind of macro can be very useful when you have
  1845. a lot of screens open.
  1846.  
  1847.      ( Bring window to front or )
  1848.      ( open it if it doesn't exist )
  1849.      : KEY_8
  1850.       0 "Palette" iWM_ACTIVATE WND_SENDMSG
  1851.       IF
  1852.         iWT_PALETTE "Palette" 200 0 60 640
  1853.         WND_OPEN
  1854.       ENDIF
  1855.       0
  1856.      ;
  1857.  
  1858.                              - TUTORIAL 7.22 -
  1859.  
  1860. When you press the key "8" the WND_SENDMSG word sends iWM_ACTIVATE message
  1861. to all "Palette" windows. If none was found, it uses the word WND_OPEN to
  1862. open one, This prevents you from accidentally opening more than one
  1863. "Palette" window.
  1864.  
  1865. The RPL "MENU" allows you to execute whatever menu through RPL. The word
  1866. takes three parameters which describes the menu to be executed.
  1867.  
  1868. For example, in order to execute the menu Create/Visible/Polygon enter the
  1869. following string in any RPL window: 1 0 0 MENU
  1870.  
  1871. then click the mouse on any View window and you can create a polygon. The
  1872. reason for this is that the "Create" menu is the second menu. Because
  1873. numbering starts from 0, the second menu corresponds the number 1.
  1874.  
  1875. The second parameter (0) defines the first menu item of "Create", which is
  1876. "Visibles". The last parameter (0) defines the first sub-menu, which is
  1877. "Polygon".
  1878.  
  1879. Naturally, you can create a word in to the rpl-startup file and call the
  1880. MENU word to activate any menu. For example, by adding the following word
  1881. to your rpl-startup file, you can activate the Lathe tool by pressing the
  1882. key "l".
  1883.  
  1884.      : KEY_l
  1885.       1 7 0 MENU ( Create/Compound_Tools/Lathe
  1886.       0
  1887.      ;
  1888.  
  1889. Note:
  1890. If the menu is "Ghosted" you cannot execute it using the mouse or a word.
  1891. Because the MENU word does the same as if you selected the actual menu,
  1892. you don't have to worry about the return value.
  1893.  
  1894. For example, the following key binding works only if the active window is
  1895. a View window.
  1896.  
  1897.      : KEY_q
  1898.       3 0 1 MENU ( View/Type/Perspective )
  1899.       0
  1900.      ;
  1901.  
  1902. The standard "rpl-startup" file contains a lot of examples of how to bind
  1903. RPL programs to keys. Take a look at it for more examples and our attempt
  1904. at a form of standardization.
  1905.  
  1906. 7.3.4 Binding Macros to Icons
  1907.  
  1908. REAL 3D allows you to create your own icons on Tool windows and bind RPL
  1909. programs to them, When the icon is clicked, the corresponding RPL program
  1910. is executed.
  1911.  
  1912. There are two kind of bindings: RPL word bindings and RPL file bindings.
  1913. In other words, the name of the icon can correspond either to the name of
  1914. the RPL word or the name of the RPL file.
  1915.  
  1916. In order to create an icon which is bound to a RPL word called HI THERE:
  1917.  
  1918. 1. Write the program containing the word HI_THERE and save it as
  1919.    "Ram:test".
  1920.  
  1921.      : HI THERE
  1922.       "YeslNo" "Are You Sure" GET_KEY
  1923.       IF
  1924.         "You are Sure" PUTS
  1925.       ELSE
  1926.         "You are not sure" PUTS
  1927.       ENDIF
  1928.       0
  1929.      ;
  1930.  
  1931. 2. Select the function Project/Macros/Execute Named and execute the macro
  1932.    "Ram:test" (or insert it to your rpl-startup file and restart Real).
  1933.  
  1934. 3. Open one Tool window.
  1935.  
  1936. 4. Select the menu Tools/Create Icons which contains one string gadget and
  1937.    two radio-buttons. Enter the string HI THERE to the string gadget and
  1938.    make sure that the radio-button "Word" is selected. Click OK and one
  1939.    icon is created on the Tool window with the text HI_THERE.
  1940.  
  1941.                              - TUTORIAL 7.23 -
  1942.  
  1943. 5. Click the icon and your HI_THERE word is called causing Real to open a
  1944.    requester with the title "Are You Sure".
  1945.  
  1946. In order to bind an icon to a file, just select the "File" radio-button
  1947. for the icon to be created and then REAL 3D attempts to load the file
  1948. whose name is the name of the gadget. REAL 3D tries to find that file from
  1949. the directory defined by Settings/Paths.
  1950.  
  1951. One very fast way to write a RPL program is to let the REAL 3D do it for
  1952. you, in other words, to record a macro:
  1953.  
  1954. 1. Create one sphere
  1955.  
  1956. 2. Activate macro recording by selecting a menu Project/Macro/Record and
  1957.    move the sphere a bit to the right.
  1958.  
  1959. 3. End macro.
  1960.  
  1961. 4. Select the menu Project/Macro/Current_To_Named. REAL 3D opens a file
  1962.    requester and allows you to define a file name for the named macro.
  1963.    Type "ram:test".
  1964.  
  1965. 5. Now create one icon on the Tool window with the name "test".
  1966.  
  1967. 6. With the sphere selected, click the icon and your sphere is moved to
  1968.    the right.
  1969.  
  1970. Note:
  1971. REAL 3D standard configuration contains the directory named "r3d2:macros".
  1972. If you put your macros there, the RPL interpreter can always find them.
  1973. Now we have gone through some basic  concepts how to customize REAL 3D by
  1974. writing RPL procedures and binding them to keys and icons. This chapter
  1975. only scratches the surface of possibilities for this customization ability
  1976. which can offer users a good basis for learning new things and get new
  1977. ideas about how to increase your productivity. The fact is that usually
  1978. you have to spent a little time to build up a new function, but once you
  1979. get it done, it can speed up your modelling in incredible ways.
  1980.  
  1981. 7.4 CREATING ANIMATIONS USING RPL
  1982.  
  1983. 7.4.1 Modifying Objects Directly
  1984.  
  1985. The animation system of REAL 3D is very sophisticated. However, there
  1986. might be some animations which cannot be created with it, simply because
  1987. they are absolutely crazy. In this section, we will learn more about RPL
  1988. by showing basic concepts about how to create these absolutely crazy
  1989. animations which cannot be created in any other way.
  1990.  
  1991. The principle is that we don't use the animation system of REAL 3D at all.
  1992. Instead we will create animations by following the procedure described
  1993. below:
  1994.  
  1995. 1. Create your scene
  1996.  
  1997. 2. Render it
  1998.  
  1999. 3. Save the rendered image (if not rendered to a file)
  2000.  
  2001. 4. Test if all frames are rendered, if they are, exit
  2002.  
  2003. 5. Do something
  2004.  
  2005. 6. Go back to the line 2.
  2006.  
  2007.                              - TUTORIAL 7.24 -
  2008.  
  2009. The line 5 (Do something) really means what it says. Because the RPL is a
  2010. full featured programming language, there is not much you can't do with
  2011. it.
  2012.  
  2013. As a matter of fact, this is the way professional animators have created
  2014. many of their really impressive animations.
  2015.  
  2016. So, lets create an animation where the object just moves with a constant
  2017. speed and direction. In order to do this, you need one View, one Select
  2018. and one RPL window.
  2019.  
  2020. Create one rectangle, select it and enter the following lines on your RPL
  2021. window:
  2022.  
  2023.      O_GETSEL
  2024.      0.1 0.2 0.0 0 M_MOVE
  2025.      REFRESH
  2026.  
  2027. This program first fetches the addresses of selected objects on the stack,
  2028. then moves the objects, and finally refreshes all windows.
  2029.  
  2030. By the way, you can enter as many commands and operands in a single line
  2031. as you wish (as long as their order is correct). For example, it is
  2032. possible to enter the previous program as follows:
  2033.  
  2034.      O_GETSEL
  2035.      0.1
  2036.      0.2
  2037.      0.0
  2038.      0
  2039.      M_MOVE
  2040.      REFRESH
  2041.  
  2042. or as follows:
  2043.  
  2044.      O_GETSEL 0.1 0.2 0.0 0 M_MOVE REFRESH
  2045.  
  2046. As you can see, moving objects are not very difficult to create. However,
  2047. they can be made even easier:
  2048.  
  2049. Write the following function:
  2050.  
  2051.      : Up
  2052.       O_GETSEL
  2053.       0 0.1 0 0 M_MOVE
  2054.       REFRESH
  2055.      ;
  2056.  
  2057. Now, make sure that the rectangle is selected and enter the following
  2058. command:
  2059.  
  2060.      Up
  2061.  
  2062. RPL moves selected primitive up and refreshes your windows.
  2063.  
  2064. Lets create another function which moves object down. It will look much
  2065. like the first one.
  2066.  
  2067.      : Down
  2068.       0 -0.1 0 0 M_MOVE
  2069.       REFRESH
  2070.      ;
  2071.  
  2072. In order to move objects up and down several times enter:
  2073.  
  2074.      Up Down Up Down Up Down Up Down
  2075.  
  2076. And all objects moved up and down several times.
  2077.  
  2078. To make up and down stuff easier to carry out, enter the following
  2079. function:
  2080.  
  2081.      : UpDown
  2082.       Up Down
  2083.       Up Down
  2084.       Up Down
  2085.       Up Down
  2086.      ;
  2087.  
  2088. Type UpDown and you rectangle will move up and down several times. This
  2089. way you can define useful functions and group them together.
  2090.  
  2091.                              - TUTORIAL 7.25 -
  2092.  
  2093. Now you know enough to create a simple animation. Create the following
  2094. program:
  2095.  
  2096.      : AnimLeft
  2097.       10 0 DO
  2098.         O_GETSEL
  2099.         -0.1 0 0 0 M_MOVE
  2100.         REFRESH
  2101.       LOOP
  2102.      ;
  2103.  
  2104. Play it and you will see that it animates all selected objects by moving
  2105. them to the left.
  2106.  
  2107.      : AnimRight
  2108.       10 0 DO
  2109.         O_GETSEL
  2110.         0.1 0 0 0 M_MOVE
  2111.         REFRESH
  2112.       LOOP
  2113.      ;
  2114.  
  2115. Call this function and it moves your objects to the right.
  2116.  
  2117. Lets create a function which moves objects first to the right, and then
  2118. back to the left:
  2119.  
  2120.      : AnimRL
  2121.       AnimRight
  2122.       AnimLeft
  2123.      ;
  2124.  
  2125. Call this function and you will see your objects moving as you expected.
  2126.  
  2127. Then let's create an animation where objects this several times:
  2128.  
  2129.      : AnimRL10
  2130.       10 0 DO
  2131.         AnimRL
  2132.       LOOP
  2133.      ;
  2134.  
  2135. Call the "Anim10" and your objects goes back and forth ten times.
  2136.  
  2137. Lets create a function, which allows you to define how many times to move
  2138. forwards and backwards:
  2139.  
  2140.      : AnimN
  2141.       0 DO
  2142.         AnimRL
  2143.       LOOP
  2144.      ;
  2145.  
  2146. You didn't enter the upper limit for the DO function inside the "AnimM"
  2147. function. So you have to pass it to the function when you call it.
  2148. Call the "AnimN" as follows:
  2149.  
  2150.      10 AnimN
  2151.  
  2152. and it goes 10 times. Call it as follows:
  2153.  
  2154.      20 AnimN
  2155.  
  2156. and your objects goes 20 times.
  2157.  
  2158. You can use the function "I" to get the current value of the "loop index"
  2159. each time around. Let's consider the following:
  2160.  
  2161.      : LoopTest
  2162.       5 -5 DO
  2163.         I.
  2164.       LOOP
  2165.      ;
  2166.  
  2167. When you call this function, the result will be:
  2168.  
  2169.      -5 -4 -3 -2 -1 0 1 2 3 4
  2170.  
  2171. You can use this index as a operand for something. For example, it can be
  2172. used as a "frame counter" or parameter to trigonometric functions for
  2173. defining nice motions.
  2174.  
  2175.                              - TUTORIAL 7.26 -
  2176.  
  2177. So, lets create an animation where all selected objects move along a sin
  2178. curve:
  2179.  
  2180.      : SinMotion
  2181.       100 0 DO
  2182.         O_GETSEL
  2183.         I 50 F/        ( x = I / 5 )
  2184.         I 10 F/ SIN F* ( y = sin 1/10 )
  2185.         0              ( z=0 )
  2186.         0
  2187.         M_MOVE
  2188.         REFRESH
  2189.       LOOP
  2190.      ;
  2191.  
  2192. Call the word "SinMotion" and all selected objects will move along a sin
  2193. curve to the positive direction of the "x" axis.
  2194.  
  2195. Loops can be nested. Write the following program:
  2196.  
  2197.      : LoopLoop
  2198.       10 0
  2199.       DO
  2200.         O_GETSEL -0.1 0 0 0 M_MOVE REFRESH
  2201.         10 0
  2202.         DO
  2203.           O_GETSEL 0 0.2 0 0 M_MOVE REFRESH
  2204.         LOOP
  2205.       LOOP
  2206.      ;
  2207.  
  2208. and call it. Selected objects move ten frames to the left, then one frame
  2209. downwards and this cycle is repeated ten times.
  2210.  
  2211. Sometimes a programmer wants to create a loop which terminates when some
  2212. condition or event occurs. BEGIN UNTIL loop can be used for this purpose.
  2213. It repeats until a condition is TRUE.
  2214.  
  2215.      : MyLoopTest
  2216.       BEGIN
  2217.         O_GETSEL 0.1 0.1 0 0 M_MOVE REFRESH
  2218.         RANDOM 0.9 F>
  2219.       UNTIL
  2220.      ;
  2221.  
  2222. Previous function loops until the RANDOM function returns the value which
  2223. is greater than 0.9. So the function UNTIL pushes one operand off the
  2224. stack and if it is non zero, the loop is terminated.
  2225.  
  2226. There are several other loops in RPL, but let's leave them for now. In the
  2227. next section you will see how to use variables in RPL. A programming
  2228. language is not a full featured programming language if it does not
  2229. support variables. So, here you go!
  2230.  
  2231.      FVARIABLE t
  2232.  
  2233.      : Rotate
  2234.       0 t F! ( t = 0 )
  2235.       BEGIN
  2236.         O_GETSEL
  2237.         t F@ SIN t F@ COS 0.0 0 M_MOVETO
  2238.         REFRESH
  2239.         t F@ 0.1 F+t F! ( t=t+0.1 )
  2240.         t F@ 3.14 F>
  2241.       UNTIL ( exit if t> 3.14 )
  2242.      ;
  2243.  
  2244. Now call this function and it moves all the selected objects along a
  2245. circular route with a radius of 1.
  2246.  
  2247. Let's improve this function a bit so that it moves the selected objects
  2248. along a circular path where the radius is passed to the function as a
  2249. operand.
  2250.  
  2251.      FVARIABLE rad
  2252.  
  2253.      : Rot2     ( radius )
  2254.       rad F! ( store user defined radius to variable "rad" )
  2255.  
  2256.       0 t F!
  2257.       BEGIN
  2258.         t F@ SIN rad F@ F* ( rad * sin t )
  2259.         t F@ COS rad F@ F* ( rad * cos t )
  2260.         0.0 ( z = 0 )
  2261.         0
  2262.         M_MOVETO
  2263.         REFRESH
  2264.         t F@ 0.1 F+ t F! (t=t+0.1 )
  2265.       t F@ 3.14 F> UNTIL ( exit if t > 3.14 )
  2266.      ;
  2267.  
  2268.                              - TUTORIAL 7.27 -
  2269.  
  2270. Call this function as follows:
  2271.  
  2272.      0.1 Rot2
  2273.  
  2274. and it will rotate all selected objects along the circular path with
  2275. radius 0.1.
  2276.  
  2277. Lets go through some lines of the previous function. The line
  2278.  
  2279.      t F@ SIN rad F@ F*
  2280.  
  2281. does the following:
  2282.  
  2283. 1. The address of the variable "t" is pushed onto the stack.
  2284.  
  2285. 2. The function "F@" pulls the address of floating-point variable from
  2286.    the stack, fetches the value from that address and pushes the value
  2287.    onto the stack.
  2288.  
  2289. 3. The function "SIN" takes one number off the stack and pushes the
  2290.    corresponding sin-value onto the stack.
  2291.  
  2292. 4. The address of "rad" variable is fetched onto the stack
  2293.  
  2294. 5. The function "F@" pushes the value from that address onto the stack
  2295.  
  2296. 6. The function "F*" takes two numbers off the stack, multiplies them and
  2297.    pushes the result back onto the stack. Later this value is passed to
  2298.    function M_MOVE, which moves selected objects in x direction
  2299.    accordingly.
  2300.  
  2301. Thats all for variables now. Just remember, when you type the name of any
  2302. variable the pointer to the variable is returned onto the stack. If you
  2303. type the string, the pointer to the string is returned onto the stack.
  2304. So far we have created just wire frame animations. Lets create a complete
  2305. ray traced animation:
  2306.  
  2307. Write the following word:
  2308.  
  2309.      : RayTrace
  2310.       10 0 DO ( ten frames )
  2311.         O_GETSEL
  2312.         0.1 0 0 0 M_MOVE
  2313.         RENDER
  2314.       LOOP
  2315.      ;
  2316.  
  2317. Now we use the word RENDER instead of REFRESH causing REAL 3D to use ray
  2318. tracing instead of wire frame rendering. However, this animation does not
  2319. yet save the rendered images. The word SCR_SAVE can be used for saving the
  2320. screen containing rendered image.
  2321.  
  2322. The following shows the complete program for creating an animation. Note
  2323. that this example assumes that your View window is opened on REAL 3D
  2324. custom screen whose name is "Real.1".
  2325.  
  2326.      100 STRING FileName
  2327.  
  2328.      : RayTraceSave
  2329.       10 0 DO
  2330.         RENDER
  2331.         I "Ram:test%d" FileName SPRINTF
  2332.         "Real.1" FileName SCR_SAVE
  2333.       O_GETSEL 0.1 0 0 0 M_MOVE
  2334.       LOOP
  2335.      ;
  2336.  
  2337. The previous program uses the word SPRINT for building up the file names
  2338. for rendered images so that the name of the first image is ram:test0
  2339. and so on.
  2340.  
  2341. The SCR_SAVE word takes two parameters: the name of the screen to be saved
  2342. and the file name.
  2343.  
  2344.                              - TUTORIAL 7.28 -
  2345.  
  2346. Right, now we have created one complete animation. Although, it is very
  2347. simple (objects just moved with constant speed along an "x" axis), it
  2348. demonstrates the basic concepts needed for creating animations using this
  2349. technique. However , there is one strange thing in this example: the
  2350. result of the animation depends on the selected objects because we used
  2351. the word O GETSEL to fetch the target objects for the M MOVE word.
  2352. Although this might give your some good ideas, it is propably not what
  2353. you wanted. So, lets create such an example where all cubes move to the
  2354. right, and all rectangles move to the left. Create some cubes and
  2355. rectangles and write the following program:
  2356.  
  2357.      100 STRING FileName
  2358.  
  2359.      : RayTraceSave
  2360.       10 0 DO
  2361.         RENDER
  2362.         I "Ram:test%d" FileName SPRINTF
  2363.         "Real.1" FileName SCR_SAVE
  2364.         "Root/cube*" O_FINDWILD 0.1 0 0 0
  2365.         M_MOVE
  2366.         "Root/rect*" O_FINDWILD -0.1 0 0 0
  2367.         M_MOVE
  2368.       LOOP
  2369.      ;
  2370.  
  2371. Right, lets leave this section now and take a look at how to create
  2372. animations using the actual Animation system of REAL 3D.
  2373.  
  2374. 7.4.2 Creating New Methods
  2375.  
  2376. In this section, we will demonstrate how to expand the animation system
  2377. of the REAL 3D by writing new animation methods.
  2378.  
  2379. As you already know, the animation system of REAL 3D is based on so
  2380. called methods. A method is a procedure which can be associated with
  2381. objects and which makes the object "intelligent enough to know what to
  2382. do when the user plays with the time controlling gadgets.
  2383. So, when do you have to create a new method?
  2384.  
  2385. Only if there are no suitable methods available. It is so easy to create
  2386. new animation methods, it is possible that somebody else has already
  2387. created a method that solves your problem (Check the REAL 3D Support BBS
  2388. for files 519-436-0140 Canada 1200 to 38400 Baud 24 hrs). Sometimes it is
  2389. also possible to get the desired result by "customizing" existing methods.
  2390. So, if there is no suitable method available and you cannot create such by
  2391. customizing existing ones, then you probably have to write your own.
  2392.  
  2393. Let's try it.
  2394.  
  2395. 7.4.2.1 Do Nothing Method
  2396.  
  2397. In this example we will learn how to create a new a method which actually
  2398. does just nothing. The purpose of this kind of silly example is just to
  2399. demonstrate the entire concept of how to attach procedures to objects in
  2400. order to make them intelligent.
  2401.  
  2402. So, start your favourite text editor program, type in the following RPL
  2403. program and save it as RAM:test.rpl.
  2404.  
  2405.      :
  2406.       DoNothing
  2407.       1
  2408.      ;
  2409.  
  2410. & DoNothing "DO NOTHING" MTH_CREATE DROP
  2411.  
  2412. Then select the menu Project/Macros/Execute Named and execute the file
  2413. RAM:test.rpl. This installs the new method to the method list of Real.
  2414.  
  2415. Select the menu Create/Structure/Method. Real opens a requester which
  2416. allows you to define the type of the method to be created. The last method
  2417. in the list should be DO NOTHING method. So, select it, click OK and you
  2418. have just created one intelligent level object.
  2419.  
  2420. Now create one target object for the method and play the animation. As
  2421. you can see, it really does nothing.
  2422.  
  2423.                              - TUTORIAL 7.29 -
  2424.  
  2425. There is only one requirement for the object procedure: it must return
  2426. either 1 or 0 (TRUE or FALSE). The return value 1 indicates that the
  2427. method in question succeeded in its mission. The return value 0 indicates
  2428. that something went wrong and the animation should be cancelled. Our
  2429. procedure "DoNothing" always returns 1 because nothing really can go
  2430. wrong.
  2431.  
  2432. The last line of the program
  2433.  
  2434. & DoNothing "DO_NOTHING" MTH_CREATE DROP
  2435.  
  2436. then installs our method to the method list of Real. The MTH_CREATE takes
  2437. two parameters: the address of the RPL word and the address of the name
  2438. for the method. So, the first command "&" just pushes the address of the
  2439. "DoNothing" word onto the stack.
  2440.  
  2441. If the creation succeeded, the MTH_CREATE word returns the address of the
  2442. created method. We are not interested in this adress so it is discarded
  2443. with the word DROP.
  2444.  
  2445. Because the DoNothing procedure is really stupid, it is easy to make it
  2446. smarter.
  2447.  
  2448. Add the following line to your "s: rpl-startup"
  2449.  
  2450.      "ram:test.rpl" LOAD
  2451.  
  2452. This installs your method automatically when you start Real.
  2453.  
  2454. Now modify the contents of the ram:test.rpl file so that the word
  2455. DoNothing actually does something:
  2456.  
  2457.      : DoNothing
  2458.       "YeslNo" "Continue" GET_KEY
  2459.      ;
  2460.  
  2461. Restart Real, create one DO_NOTHING method and play the animation.
  2462. Requester is opened with the header text "Continue" and two gadgets "Yes"
  2463. and "No". If you select "No" gadget, the GET_KEY returns 0 and the
  2464. animation is terminated. If you select "Yes" gadget, the GET_KEY returns
  2465. 1 and Real proceeds to the next frame asking you the same question again.
  2466. Before we leave this DO_NOTHING example, let's do something useful. Let's
  2467. create one real animation method which moves the target objects randomly.
  2468. So, modify the "ram:test.rpl" file so that the DoNothing word looks like
  2469. the following.
  2470.  
  2471.      : DoNothing
  2472.       0 o2 @ RANDOM RANDOM RANDOM 0
  2473.       M_MOVETO
  2474.       1
  2475.      ;
  2476.  
  2477. Now, restart Real, create one DO_NOTHING method with some targets and play
  2478. the animation. Now we have finally managed to get something which looks
  2479. like an animation.
  2480.  
  2481. The reason why we first showed these silly "do nothing" examples was that
  2482. it is important to realize that it is totally up to the user to decide
  2483. what his/her object procedures (methods) should do. They can be simple or
  2484. complex and tailored to address specific needs of the user.
  2485.  
  2486. 7.4.2.2 Move Absolutely Along a Path
  2487.  
  2488. In this example, we will demonstrate how to create a method which moves
  2489. target objects along a path so that if the target is dislocated from the
  2490. path, it is immediately pulled back to it. This is very good example,
  2491. because it demonstrates how powerful a tool RPL is and how user created
  2492. methods expand the functionality of the program.
  2493.  
  2494. The first thing to do is to decide what kind of properties our custom
  2495. methods should have and what kind of parameteres it requires. In this
  2496. case our method strongly resembles the PATH methods.
  2497.  
  2498. So, the syntax diagram of the method looks like the following:
  2499.  
  2500.           +--------+
  2501.           | Parent |
  2502.           +--------+
  2503.             /     \
  2504.      +--------+ +----------+
  2505.      | target | | Level(M) |
  2506.      +--------+ +----------+
  2507.                       \
  2508.                   +------+
  2509.                   | Path |
  2510.                   +------+
  2511.  
  2512.                              - TUTORIAL 7.30 -
  2513.  
  2514. Next we have to work out what the procedure to be created should do. In
  2515. this case, it should do the following things:
  2516.  
  2517. - Read the current time
  2518.  
  2519. - Evaluate one point from the parameter object corresponding to the
  2520.   current time.
  2521.  
  2522. - Move target object(s) to the evaluated point.
  2523.  
  2524. So, when the time runs from 0 up to 1, the evaluated points move along the
  2525. parameter object from its beginning point towards its end point
  2526. accordingly pulling all target objects with it.
  2527.  
  2528. The following program defines AbsPath method procedure and adds a new
  2529. animation method to the Animation System.
  2530.  
  2531.      ( Load definitions for object data structure "objects. rpl" LOAD
  2532.  
  2533.      ( One general usage support word
  2534.      : GetTargets
  2535.       0 ( 0 terminates the list
  2536.       o2 @ O_GETSUB ( first subobject
  2537.       BEGIN
  2538.         ( test if the object address is not zero
  2539.         DUP IF
  2540.           ( fetch the contents of wMETHOD field:
  2541.           DUP O.wMETHOD W@
  2542.           NOT IF ( if zero, valid target
  2543.             DUP
  2544.           ENDIF
  2545.         ELSE ( object address was zero, so
  2546.           EXIT ( no more targets, exit the word
  2547.         ENDIF
  2548.         ( fetch the address of the next object:
  2549.         O_GETNEXT
  2550.       AGAIN
  2551.      ;
  2552.  
  2553.      ( Actual object procedure
  2554.      : AbsPath
  2555.       GetTargets ( fetch target objects on the stack
  2556.       o1 @ O_GETSUB ( find the parameter object
  2557.       DUP NOT IF ( if no parameter, syntax error
  2558.         "Parameter Object Missing" PUTS
  2559.         0 ( cancel animation
  2560.         EXIT ( exit word
  2561.       ENDIF
  2562.       t F@ u F@ v F@ O_EVAL 0
  2563.       M_MOVECOG
  2564.       1 ( return 1, everything is okay
  2565.      ;
  2566.  
  2567.      ( Install new method to the animation system
  2568.      & AbsPath "ABS_PATH" MTH_CREATE DROP
  2569.  
  2570. As you can see, it takes only some lines of RPL code to define a
  2571. completely new animation method. After executing the program, one new
  2572. method called ABS_PATH can be seen in the Create/Structure/Method
  2573. requester.
  2574.  
  2575. The word GetTargets is a general usage word which can be used by all your
  2576. custom methods. It just fetches the addresses of all target objects on the
  2577. stack and terminates the list with 0 as required by M_XXXX words.
  2578.  
  2579. The variables "o1", "o2" and "t", "u", and "v" are automatically defined
  2580. by the animation system. "o1" contains the address of the method object,
  2581. "o2" contains the address of the parent object of method and t, u and v
  2582. variables reflects the new time for the method.
  2583.  
  2584. So, let's take a look at what the actual method procedure does.
  2585.  
  2586. Whenever the time is changed, the animation system calls our procedure
  2587. AbsPath.
  2588.  
  2589. As already mentioned, the word:
  2590.  
  2591.      GetTargets
  2592.  
  2593. just pushes the addresses of all target objects on the stack. Then the
  2594. line
  2595.  
  2596.      o1 @ O_GETSUB
  2597.  
  2598.                              - TUTORIAL 7.31 -
  2599.  
  2600. fetches the address of the parameter object on the stack (parameter object
  2601. is sub object of the method object).
  2602.  
  2603. The code:
  2604.  
  2605.      DUP NOT IF
  2606.         "ERROR: Parameter Object Missing" PUTS
  2607.         0 EXIT
  2608.      ENDIF
  2609.  
  2610. then tests the return value of O_GETSUB and if 0, proper error message is
  2611. printed out and 0 returned indicating that the method failed. The return
  2612. value of 0 causes animation system to stop.
  2613.  
  2614. Otherwise the code after ENDIF is executed:
  2615.  
  2616.      t F@ u F@ v F@ O_EVAL 0 M_MOVECOG
  2617.      1
  2618.  
  2619. which evaluates a point from the parameter curve and moves all targets to
  2620. that point. Finally the value 1 is pushed on the stack, which indicates
  2621. that method succeeded in its task.
  2622.  
  2623. 7.4.2.3 Chain
  2624.  
  2625. In this example, we will create a method which attempts to keep the
  2626. distance between subsequent target objects constant. The distance between
  2627. targets can be defined by associating a tag with the method object. If
  2628. the tag does not exists, then our method uses default value, say 0.5.
  2629. This method can be very powerful with some particle system oriented
  2630. methods like radial force etc.
  2631.  
  2632. Our methods should do the following things:
  2633.  
  2634. 1. Find the tag value of "FDIS" tag associated with the method object.
  2635.  
  2636. 2. Loop through all targets and move them so that the distance between
  2637.    COGs of subsequent targets equals the fetched tag value.
  2638.  
  2639. Note:
  2640. That we use vector operations here.
  2641.  
  2642. Note:
  2643. That this requires some basic knowledges of vector operations like how
  2644. to add and subtract vectors.
  2645.  
  2646.      ( Useful support function Distribute
  2647.  
  2648.      FVARIABLE fLen
  2649.      VVARIABLE vTmp
  2650.  
  2651.      : Distribute ( 0 aObjects .... fDist )
  2652.       fLen F!
  2653.       iOP_COG O_PROP vTmp V!
  2654.       BEGIN
  2655.         DUP
  2656.       WHILE
  2657.         DUP iOP_COG O_PROP
  2658.         vTmp V@ VSUB VNORM
  2659.         fLen F@ VMUL
  2660.         vTmp V@ VSUB vTmp V!
  2661.         0 SWAP vTmp V@ 0 M_MOVECOG
  2662.       REPEAT
  2663.       DROP
  2664.      ;
  2665.  
  2666.      ( Actual Object Procedure
  2667.  
  2668.      : OP_Chain
  2669.       GetTargets
  2670.       o1 @ "FDIS" O_FINDTAG DUP ( find tag FDIS
  2671.       IF ( if found, fetch its value on the stack:
  2672.         4 + @ F@
  2673.       ELSE
  2674.         DROP 0.5 ( else push 0.5 on the stack
  2675.       ENDIF
  2676.       ( call distribute with objects and distance:
  2677.       Distribute
  2678.       1
  2679.      ;
  2680.  
  2681.       & OP_Chain "CHAIN" MTH_CREATE DROP
  2682.  
  2683.                              - TUTORIAL 7.32 -
  2684.  
  2685. Again, we divided our method into two different words: Distribute and the
  2686. actual object procedure OP_Chain. The reason for this is that
  2687. "Distribute" is in general usage a useful word and it is a good
  2688. programming practice to write modular programs by subdividing bigger tasks
  2689. to smaller ones. For example, your can apply the "Distribute" now
  2690. interactively to selected objects by defining just a core word which uses
  2691. the GET_FLT and O_GETSEL words for fetching the required parameters for it
  2692. instead of using O_FINTAG and GetTargets as we did here.
  2693.  
  2694. The Distribute words take the following parameters:
  2695.  
  2696. - object list terminated with 0
  2697. - distance
  2698.  
  2699. The first line
  2700.  
  2701.      fLen F!
  2702.  
  2703. Just assigns the passed distance parameter to the variable "fLen". This
  2704. makes it easy to use all over because we don't have to remember where
  2705. it is in the stack.
  2706.  
  2707. The next line starts the actual job:
  2708.  
  2709.      iOP_COG O_PROP vTmp V!
  2710.  
  2711. O_PROP word is first used for fetching the COG of the first object on the
  2712. stack and assigns it to the vector variable vTmp.
  2713.  
  2714. Then in the beginning of the loop:
  2715.  
  2716.      DUP iOP_COG O_PROP
  2717.  
  2718. fetches the COG of the second object on the stack.
  2719.  
  2720. The line
  2721.  
  2722.      vTmp V@ VSUB VNORM
  2723.  
  2724. fetches the COG of the first object on the stack, subtracts the COG of the
  2725. second object from the COG of the first object and finally normalizes the
  2726. result vector so that the lenght of it will be 1.
  2727.  
  2728. The line
  2729.  
  2730.      fLen F@ VMUL
  2731.  
  2732. then multiplies the unit vector by given distance. Now the length of the
  2733. vector is given distance and it points from the second object towards the
  2734. first one. Then we have to subtract it from the COG of the first object
  2735. and we get the position for the second object. The following line
  2736. subtracts the vector from the COG of the first object and saves the result
  2737. back to the vTmp.
  2738.  
  2739.      vTmp V@ VSUB vTmp V!
  2740.  
  2741. Then we just move the second target object to the defined point.
  2742.  
  2743.      0 SWAP vTmp V@ 0 M_MOVECOG
  2744.  
  2745. There is not much to tell about the actual object procedure OP Chain. It
  2746. uses the word "GetTargets" to fetch the addresses of target objects on the
  2747. stack, the distance to be used from the tag FDIS (or uses the value 0.5 if
  2748. the tag does not exists) and then calls the word Distribute which does the
  2749. actual job. Because the method cannot fail, it always returns 1.
  2750.  
  2751. Before we leave this method example, let's take a look at how the
  2752. Distribute word can be used interactively.
  2753.  
  2754. 1. Open one RPL window and define the word Distribute.
  2755.  
  2756. 2. Create 10 spheres resembling pearl necklace.
  2757.  
  2758. 3. Write the following program:
  2759.  
  2760.      FVARIABLE fDistance
  2761.  
  2762.      : Distr
  2763.       fDistance "Define Distance" GET_FLT
  2764.       IF
  2765.         O_GETSEL fDistance f@ Distribute
  2766.       ENDIF
  2767.      ;
  2768.  
  2769. 4. Select all spheres and call the word "Distr".
  2770.  
  2771.                              - TUTORIAL 7.33 -
  2772.  
  2773. 7. 4.2.4 Strange Force
  2774.  
  2775. In this example we will create a method object which applies a very
  2776. strange force field over targets causing the velocity and the spin of
  2777. target objects to be changed . This is an absolutely crazy method, because
  2778. the way we modify the velocity is absolutely random and it might be quite
  2779. a difficult job to find such a force field in the real world. However, it
  2780. demonstrates well the concept of designing new physical based methods and
  2781. how to create and update object tags.
  2782.  
  2783. First we need a word which defines a direction and the strength of the
  2784. force field.
  2785.  
  2786.      : GetStrangeForce
  2787.       RANDOM RANDOM RANDOM
  2788.      ;
  2789.  
  2790. Because we separate the word which defines the strength and direction for
  2791. the force, it is very easy to change this method just by modifying this
  2792. word.
  2793.  
  2794. Then we need a word which attemps to read the value of velocity tag. If
  2795. the VVEL tag does not exist, then it creates it. If the velocity tag
  2796. exists, then the method modifies its value according to Newtons Laws of
  2797. Motion. So, how much should the velocity of the object be changed if the
  2798. force affects the object for "dt" seconds? According to Mr Newton, the
  2799. strength of the force equals the mass of the object multiplied by the
  2800. acceleration. Mathematically the problem can be solved as follows:
  2801.  
  2802.      F=ma => F=m*dv/dt => dv = F*dt/m
  2803.                           -----------
  2804.  
  2805. Because our force is not sensitive to the mass of the target object, we
  2806. can forget the mass (m). Hence, the new velocity can be solved from the
  2807. equation:
  2808.  
  2809.      dv = F*dt
  2810.      ---------
  2811.  
  2812. The following word does all this:
  2813.  
  2814.      ( Word modifying the velocity )
  2815.      ( of a given object )
  2816.       : DoStrangeVEL ( aObj )
  2817.         "VVEL" O_FINDTAG DUP
  2818.         ( try to find VVEL tag
  2819.         IF ( if found:
  2820.           4 + @ ( fetch the address of tag value
  2821.           DUP V@ ( fetch the velocity on the stack
  2822.           ( fetch the force vector on the stack:
  2823.           GetStrangeForce
  2824.           dt F@ VMUL ( dv = F* dt
  2825.           ( add "dv" vector to original velocity:
  2826.           VADD
  2827.           ( assign result back to the velocity tag:
  2828.           4 ROLL V!
  2829.         ELSE
  2830.           DROP DUP "CEND" 0 0 0 "VVEL"
  2831.           O_CREATAG DROP
  2832.         ENDIF
  2833.      ;
  2834.  
  2835. In order to get the new particle method perfect, also the spin must be
  2836. affected somehow. The only difference between this and the DoStrangeSPI
  2837. words is that the result vector for the VSPI tag is multiplied by 2*PI.
  2838. This is because the spin is represented in radians and 2*PI radians
  2839. corresponds to a full circle (360 deg).
  2840.  
  2841.      ( A word modifying the spin of the object )
  2842.      : DoStrangeSPI ( aObj )
  2843.       "VSPI" O_FINDTAG DUP
  2844.       IF
  2845.         4 + @ DUP V@ ( original spin
  2846.         GetStrangeForce dt F@
  2847.         2 PI F* F* VMUL ( delta
  2848.         VADD ( new spin
  2849.         4 ROLL V ( assign result to VSPI
  2850.       ELSE
  2851.         DROP DUP "CEND" 0 0 0 "VSPI"
  2852.         O_CREATAG DROP
  2853.       ENDIF
  2854.      ;
  2855.  
  2856.                              - TUTORIAL 7.34 -
  2857.  
  2858. The actual object procedure then just scans through all targets and calls
  2859. DoStrangeVEL and DoStrangeSPI words for each object.
  2860.  
  2861.      : OP StrangeForce
  2862.       GetTargets
  2863.       BEGIN
  2864.         DUP
  2865.       WHILE
  2866.         DUP
  2867.         DoStrangeVEL
  2868.         DoStrangeSPI
  2869.       REPEAT
  2870.       DROP
  2871.       1
  2872.      ;
  2873.  
  2874. & OP StrangeForce "STRANGE_FORCE" MTH_CREATE DROP
  2875.  
  2876. 7.5 USING EVAL
  2877.  
  2878. The EVAL word provides the user with an easy way to access data structures
  2879. of Real, such as materials and objects. In this chapter we will show you
  2880. some basic ways to use EVAL.
  2881.  
  2882. Create one material with all properties set to default.
  2883.  
  2884. How to set the brilliancy of the created material "mymat to 100? Type the
  2885. following line:
  2886.  
  2887.      "data(mymat->spec)=100" EVAL DROP
  2888.  
  2889. You just set the specularity of "mymat" to 100. To make sure that this
  2890. really happened, open the material requester with the material and see.
  2891.  
  2892. If you don't like Reverse Polish Notation, you can use eval to evaluate
  2893. your formulas like this:
  2894.  
  2895.      "2*3+5" EVAL .
  2896.  
  2897. which is the same as the phrase "2 3 * 5 + ." and RPL will reply:
  2898.  
  2899.      11
  2900.  
  2901. or like this:
  2902.  
  2903.      "2*3*sin(3*cos(123)+3)" EVAL F.
  2904.  
  2905. or like this:
  2906.  
  2907.      "data(mymat->spec)=(data(mymat->bril)
  2908.      +data(mymat->tran))/2" EVAL.
  2909.  
  2910. and RPL calculates an average of the brilliancy and transparency and
  2911. assigns these results into a specularity field.
  2912.  
  2913. So, let's create a material morphing animation. Create one sphere and add
  2914. material "mymat" to it by creating one texture at the same level.
  2915. Ensure that the rendering settings for the current View window are correct
  2916. (don't use the Fast-mode because it ignores all material properties).
  2917.  
  2918. Then write the following program:
  2919.  
  2920.      VARIABLE rg
  2921.  
  2922.      : MyAnim
  2923.       10 0 DO ( ten frames )
  2924.         I 10 * rg! ( rg=I*10 )
  2925.         "data(mymat->roug)=rg" EVAL DROP
  2926.         RENDER
  2927.       LOOP
  2928.      ;
  2929.  
  2930. and everything is ready for the show.
  2931.  
  2932. Call the previous function and you'll see how the roughness of your
  2933. rectangle is morphed during the animation.
  2934.  
  2935. Right, how about objects. Assume that the full name (including the path)
  2936. for you rectangle is "/Root/rectangle". Then you could print out the
  2937. color of you rectangle as follows:
  2938.  
  2939.      "data(/Root/rectangle->R)" EVAL.
  2940.      "data(/Root/rectangle->G)" EVAL.
  2941.      "data(/Root/rectangle->B)" EVAL.
  2942.  
  2943.                              - TUTORIAL 7.35 -
  2944.  
  2945. or you can change the red signal of the color as follows:
  2946.  
  2947.      "data(/Root/rectangle->R)=120" EVAL.
  2948.  
  2949. or you can print out the name of your object as follows:
  2950.  
  2951.      "data(/Root/rectangle->name)" EVAL PUTS
  2952.  
  2953. or you can change the line pattern of your rectangle as follows:
  2954.  
  2955.      "data(/Root/rectangle->ptrn)=255" EVAL.
  2956.      REFRESH
  2957.  
  2958. or you can change the register color for wire frame rendering:
  2959.  
  2960.      data(/Root/rectangle-> reg)= 3" EVAL.
  2961.      REFRESH
  2962.  
  2963. For more about EVAL, see the reference manual.
  2964.  
  2965. 7.6 OBJECTS
  2966.  
  2967. In this section, we will demonstrate how RPL can be used for creating and
  2968. manipulating objects.
  2969.  
  2970. 7.6.1 Object Creation
  2971.  
  2972. So, let's get started by creating a simple RPL program which just creates
  2973. one primitive and renders it using default rendering settings.
  2974.  
  2975.      ( A minimal program for rendering a sphere
  2976.      0.0  0.0  0.0  ( center )
  2977.      0.5  0.0  0.0  ( a )
  2978.      0.0  0.5  0.0  ( b )
  2979.      0.0  0.0  0.5  ( c )
  2980.      255 0 0 0      ( RGBA )
  2981.      "ellipsoid"    ( name )
  2982.      0              ( flags )
  2983.      "CEND"         ( tags )
  2984.      C_ELLIPSOID DROP
  2985.  
  2986.      RENDER
  2987.  
  2988. When passed to REAL 3D's stand-alone renderer, it should produce an image
  2989. representing one red sphere.
  2990.  
  2991. Lets go through what this program actually does.
  2992.  
  2993. The first word C_ELLIPSOID creates an ellipsoid. The general form of all
  2994. creation words is as follows:
  2995.  
  2996.      Geometry Color Attributes C_nnnn Address
  2997.  
  2998. Geometric data is described first (in the example it consists of four
  2999. vectors: center, a, b, and c). The form of geom. data depends on the
  3000. type of the object to be created. Not all objects have geometric
  3001. description. In this example, the geom. data defines a sphere, because
  3002. the length of all three axes are the same.
  3003.  
  3004.      ( Geometric data for ellipsoid )
  3005.      0.0 0.0 0.0 ( center )
  3006.      0.5 0.0 0.0 ( a )
  3007.      0.0 0.5 0.0 ( b )
  3008.      0.0 0.0 0.5 ( c )
  3009.  
  3010. The second data section is a color for the object. Color is defined by 32
  3011. bits (RGB+A). Like geom. description, not all objects have color section.
  3012.  
  3013.      ( Color is defined by 32 bits R,G,B+A )
  3014.      255 0 0 0   ( RGBA )
  3015.  
  3016. The third data section defines so called "Attributes" for objects.
  3017. Attributes can be divided into three different parts: name, flags and tag
  3018. list. The name field defines a symbolic name for the object. This name can
  3019. be used in many ways. For example, it can be used for finding the address
  3020. of the object in order to create new objects, more on this later.
  3021.  
  3022. The flags field is a 32 bit wide integer value. It is used for defining
  3023. on/off kinds of attributes like whether or not this object should be
  3024. "motion blurred" or "invisible". In the REAL 3D Editor, these flags can be
  3025. defined using Modify/Properties/Attributes function. For more information
  3026. about possible attribute flags, see the reference manual.
  3027.  
  3028.                              - TUTORIAL 7.36 -
  3029.  
  3030. The tag list can be used for defining custom attributes for objects needed
  3031. by procedural textures, animation methods etc. The tag list consists of a
  3032. number of tag identifier-value pairs. The tag value is a string whose
  3033. length is four characters which identifies the value. The type of the tag
  3034. value then depends on the tag identifier. The tag list is always
  3035. terminated by "CEND" string.
  3036.  
  3037.      ( Attributes )
  3038.      "ellipsoid" ( name )
  3039.      0           ( flags )
  3040.      "CEND"      ( tags )
  3041.  
  3042. C_ELLIPSOID creates an ellipsoid and returns the address. This address can
  3043. be used in many ways as we will later see. In this example, it is not
  3044. needed, so it is discarded by using the word DROP.
  3045.  
  3046. The last word "RENDER" then asks REAL 3D to render the defined scene which
  3047. in this example consists of only one sphere.
  3048.  
  3049. One basic idea of RPL is that at the lowest level all data needed for
  3050. defining objects must be passed to the RPL interface! There are no
  3051. graphical environments used for defining parts of the data needed as in
  3052. Renderman.
  3053.  
  3054. However , this does not mean that in the case where a scene consists of a
  3055. large number of almost identical objects the program would have to
  3056. redefine the same data again for each object. Because RPL is a full
  3057. featured programming language, there are many ways to solve this problem.
  3058.  
  3059. For instance, let us imagine a scene consisting of 10 spheres. Would it
  3060. take ten times more space to create such a scene as a scene which consists
  3061. of only one sphere? Only if all the objects are totally different. Usually
  3062. they are not, in which case identical data could be defined using, for
  3063. example, a separate RPL word instead of redefining it for all primitives.
  3064.  
  3065. Lets demonstrate this by creating an RPL program. The program would create
  3066. two identical spheres to different position.
  3067.  
  3068.      ( A simple program implementing graphics )
  3069.      ( environment using different RPL words )
  3070.      : MY ELLIPSOID ( center addr )
  3071.       0.5 0.0 0.0 ( a )
  3072.       0.0 0.5 0.0 ( b )
  3073.       0.0 0.0 0.5 ( c )
  3074.       255 0 0 0   ( RGBA )
  3075.       "ellipsoid" ( name )
  3076.       0           ( flags )
  3077.       "CEND"      ( tags )
  3078.       C_ELLIPSOID
  3079.      ;
  3080.  
  3081.       0 0 0       ( center )
  3082.       MY_ELLIPSOID DROP
  3083.  
  3084.       1 0 0       ( center )
  3085.       MY_ELLIPSOID DROP
  3086.  
  3087. RENDER
  3088.  
  3089. To make this clear, let's create another program. The program creates a
  3090. small "Renderman" style graphical environment used for defining
  3091. "Attribute" data section for objects to be created.
  3092.  
  3093.      ( data for simple graphics environment )
  3094.       VARIABLE R
  3095.       VARIABLE G
  3096.       VARIABLE B
  3097.       VARIABLE FLAGS
  3098.       16 STRING NAME
  3099.  
  3100.      ( words for manipulating )
  3101.      ( graphics environment )
  3102.      : RiName ( name - )
  3103.       NAME CPY
  3104.      ;
  3105.  
  3106.      : RiColor ( R G B - )
  3107.       B!G!R!
  3108.      ;
  3109.  
  3110.      : RiFlags ( Flags - )
  3111.       FLAGS !
  3112.      ;
  3113.  
  3114.                              - TUTORIAL 7.37 -
  3115.  
  3116.      ( Ri style interface for creating )
  3117.      ( an ellipsoid )
  3118.      : RiEllipsoid ( center, a, b, c - )
  3119.      ( fetch color from graphics environment )
  3120.      R @ G @ B @ 0 ( A=0 )
  3121.      NAME ( fetch the address of the name )
  3122.      FLAGS @ ( fetch flags )
  3123.      "CEND" ( no tags )
  3124.      C_ELLIPSOID DROP
  3125.      ;
  3126.  
  3127.      ( create 3 blue spheres )
  3128.      0 0 255 0 RiColor
  3129.      0 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
  3130.      1 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
  3131.      2 0 0 1 0 0 0 1 0 0 0 1 RiEllipsoid
  3132.  
  3133.      ( create 2 red ellipsoids )
  3134.      255 0 0 RiColor
  3135.      0 1 0 0.5 0 0 0 1 0 0 0 1 RiEllipsoid
  3136.      0 2 0 0.5 0 0 0 1 0 0 0 1 RiEllipsoid
  3137.  
  3138.      ( create one green ellipsoid, "blue" )
  3139.      0 255 0 RiColor
  3140.      "blue" RiName
  3141.      0 -1 0 0.5 0 0 0.8 0 0 0 1.2 RiEllipsoid
  3142.  
  3143. This listing defines a custom interface where geometric data is defined by
  3144. the caller and the attributes are fetched from the graphics environment.
  3145.  
  3146. 7.6.2 Object Instances
  3147.  
  3148. RPL allows creation of "object instances". This is a useful feature
  3149. whenever it takes less space to define geometric transformations and
  3150. modify new objects out of existing ones than defining object data itself.
  3151. The following example creates a number of spheres using this technique.
  3152.  
  3153.      FVARIABLE Rad
  3154.      VARIABLE Obj
  3155.      ( create first object )
  3156.      : MY SPHERE  ( center rad - addr )
  3157.       Rad F!      ( assign radius to variable "rad" )
  3158.       Rad F@ 0 0  ( a )
  3159.       0 Rad F@ 0  ( b )
  3160.       0 0 Rad F@  ( c )
  3161.       255 0 0 0   ( RGBA )
  3162.       "ellipsoid" ( name )
  3163.       0           ( flags )
  3164.       "CEND"      ( tags )
  3165.       C_ELLIPSOID
  3166.      ;
  3167.  
  3168.      0 0 0 0.5 MY_SPHERE Obj !
  3169.  
  3170.      ( create two object instances )
  3171.      ( from the first one )
  3172.      Obj @ M DUPLICATE 0 SWAP
  3173.      1.5 0.2 0.2 0 M_MOVE
  3174.      ( the second one: )
  3175.      Obj @ M_DUPLICATE 0 SWAP
  3176.      255 255 0 0 1 0 M_COLOR
  3177.  
  3178. The word MY SPHERE takes two parameters which are center and radius and
  3179. returns an address of the created sphere.
  3180.  
  3181. The line
  3182.  
  3183.      0 0 0 0.5 MY_SPHERE Obj !
  3184.  
  3185. creates one sphere whose center is 0,0,0 and radius 0.5. The return value
  3186. from the C_ELLIPSOID is not discarded using DROP but returned so that it
  3187. can be stored into the variable "Obj".
  3188.  
  3189. The last two lines contain the big idea so lets go through them line by
  3190. line:
  3191.  
  3192.      Obj @    ( fetch the address of the sphere
  3193.      M_DUPLICATE ( duplicate it and leave
  3194.                  ( its address on to the stack
  3195.  
  3196.                              - TUTORIAL 7.38 -
  3197.  
  3198. For the sake of efficiency, more than one object can be modified by RPL
  3199. modify words at one call. The address 0 means that there are no more
  3200. object addresses in the stack. So the following expression:
  3201.  
  3202.      0 SWAP
  3203.  
  3204. just terminates the object pointer list by 0.
  3205.  
  3206.      1.5 0.2 0.2 0 M_MOVE
  3207.  
  3208. then moves object instance 1 .5 along x axis and 0.2 along y and z axes.
  3209. The second instance is created by changing the color of the sphere from
  3210. red to yellow.
  3211.  
  3212. 7.6.3 Grouping Objects Together
  3213.  
  3214. Objects can be grouped together to create hierarchical object trees. This
  3215. hierarchical construction of object conforms the basis for a large number
  3216. of other features of RPL.
  3217.  
  3218. The word C_LEVEL can be used for creating new levels into the object
  3219. hierarchy and its syntax is as follows:
  3220.  
  3221.      Type Attributes C_LEVEL Addr
  3222.  
  3223. The following example creates one simple object tree using the word
  3224. MY_SPHERE created in the previous example. The structure of the tree to
  3225. be represented is as follows:
  3226.  
  3227.            +------+
  3228.            | Root |
  3229.            +------+
  3230.             /    \
  3231.      +--------+ +-----+
  3232.      | Sphere | | Sub |
  3233.      +--------+ +-----+
  3234.                  /   \
  3235.          +--------+ +--------+
  3236.          | Sphere | | Sphere |
  3237.          +--------+ +--------+
  3238.  
  3239. The following program builds up the hierarchy.
  3240.  
  3241.      ( Creating a simple hierarchical object )
  3242.       wOT_OR "Root" 0 "CEND" C_LEVEL
  3243.       O_CURRENT DROP
  3244.  
  3245.         0 0 0 0.5 MY_SPHERE DROP
  3246.         wOT OR "Sub" 0 "CEND" C_LEVEL
  3247.         O_CURRENT
  3248.  
  3249.           0 0 0 0.5 MY_SPHERE DROP
  3250.           0 0 0 0.5 MY_SPHERE DROP
  3251.  
  3252.         O_GETCURR O_GETPAR O_CURRENT
  3253.         DROP
  3254.  
  3255. The first two lines
  3256.  
  3257.      wOT_OR "Root" 0 "CEND" C_LEVEL
  3258.      O_CURRENT DROP
  3259.  
  3260. create one object of the type wOT_OR. The constant named "wOT_OR" is
  3261. defined "objects.rpl" in file and the actual value of it is 2. By using
  3262. constants makes the type of the level more easy to understand for human
  3263. beings. It is strongly recommended to use these kind of definitions
  3264. instead of direct values. The first parameter "wOT_OR" defines how volumes
  3265. of all sub objects are interpreted. In this example, they are "OR" read
  3266. with each other.
  3267.  
  3268. The following fields
  3269.  
  3270.      "Root" 0 "CEND"
  3271.  
  3272. defines attributes for the object and are identical with those we have
  3273. already seen in previous examples.
  3274.  
  3275. The word
  3276.  
  3277.      O_CURRENT
  3278.  
  3279. takes one parameter, which is an address of an object and makes it the
  3280. current level so that all latter objects will be created inside it. The
  3281. word returns the address of the previous current level and we get rid of
  3282. it using the DROP word.
  3283.  
  3284.                              - TUTORIAL 7.39 -
  3285.  
  3286. The creation of the second level is similar to the first one except for
  3287. two things: the name of the level to be created is now "Sub" and we don't
  3288. delete the return value from the O_CURRENT. We leave it on the stack so
  3289. that we can use it later to pop back to the previous level using
  3290.  
  3291.      O_GETPAR and
  3292.      O_CURRENT words.
  3293.  
  3294. O_GETPAR takes the address of an object and returns the address of its
  3295. parent object. Then O_CURRENT makes it the new current level.
  3296.  
  3297. Althought all previous words are pretty simple and clear, our example
  3298. itself is not perhaps as clear as it could be. The reason for this is that
  3299. it shows how to built up a hierarchy at the lowest level. Again, it is not
  3300. necessary to define all parameters for C_LEVEL every time a new level is
  3301. created. We can create our own core word, which takes only the name of the
  3302. level to be created.
  3303.  
  3304. In the following example we will create some useful words which reduce the
  3305. size of the program and make it much more understandable.
  3306.  
  3307.      ( create level )
  3308.      : ObjBegin ( name )
  3309.       wOT_OR SWAP 0 "CEND" C_LEVEL
  3310.       O_CURRENT DROP
  3311.      ;
  3312.  
  3313.      ( close level )
  3314.      : ObjEnd
  3315.       O_GETCURR O_GETPAR O_CURRENT DROP
  3316.      ;
  3317.  
  3318.      "Root" ObjBegin
  3319.       0 0 0 0.5 MY_SPHERE DROP
  3320.       "Sub" ObjBegin
  3321.         0 0 0 0.5 MY_SPHERE DROP
  3322.         0 0 0 0.5 MY_SPHERE DROP
  3323.       ObjEnd
  3324.      ( Now words ObjBegin and ObjEnd )
  3325.      ( can be used for defining hierarchy )
  3326.  
  3327. It is very easy to close the hierarchy levels by leaving the return
  3328. address of each created level on the stack and pull it out when it is
  3329. needed. To get the parent object of it in order to pop up one hierarchy
  3330. level. However, sometimes it is easier to build up the hierarchy first
  3331. and then create the actual primitives. For example, let's build up a
  3332. hierarchical tree which contains no primitives. The structure of the tree
  3333. should be as follows:
  3334.  
  3335.               +------+
  3336.               | Root |
  3337.               +------+
  3338.              /   |    \
  3339.             /    |     \
  3340.      +------+ +------+ +------+
  3341.      | Sub1 | | Sub2 | | Sub3 |
  3342.      +------+ +------+ +------+
  3343.                 / \
  3344.                /   \
  3345.         +-------+ +-------+
  3346.         | Sub21 | | Sub22 |
  3347.         +-------+ +-------+
  3348.                      / \
  3349.                     /   \
  3350.             +--------+ +--------+
  3351.             | Sub221 | | Sub222 |
  3352.             +--------+ +--------+
  3353.  
  3354. Using the words ObjBegin/ObjEnd defined in previous example a program
  3355. would look as follows:
  3356.  
  3357.      ( Building up an empty hierarchy )
  3358.      "Root" ObjBegin
  3359.       "Sub1" ObjBegin
  3360.       ObjEnd
  3361.       "Sub2" ObjBegin
  3362.         "Sub21" ObjBegin
  3363.         ObjEnd
  3364.         "Sub22" ObjBegin
  3365.           "Sub221 ObjBegin
  3366.           ObjEnd
  3367.           "Sub222 ObjBegin
  3368.         ObjEnd
  3369.       ObjEnd
  3370.      ObjEnd
  3371.  
  3372. Because we discarded all addresses of created objects using the DROP word
  3373. in the ObjBegin word, we don't remember any addresses of any objects. So,
  3374. how do we create something inside the desired hierarchy level? The address
  3375. of any object can be found by its name. For example, we could create a
  3376. sphere inside the object named "sub222" as follows:
  3377.  
  3378.                              - TUTORIAL 7.40 -
  3379.  
  3380.      ( find the address of object )
  3381.      "/Root/Sub2/Sub22/Sub221" O_FIND
  3382.      O_CURRENT DROP ( make it current )
  3383.      ( create one sphere )
  3384.      0 0 0 0.5 MY_SPHERE DROP
  3385.  
  3386. Another possibility is to use variables to store object addresses instead
  3387. of fetching addresses using the O_FIND word.
  3388.  
  3389. 7.6.4 SphereMan
  3390.  
  3391. As a final example for this RPL tutorial, we will go through how to create
  3392. "freeform objects" consisting of thousands of particles. For example, a
  3393. body of the human being can be created using thousands of spheres
  3394. distributed evenly over the body instead of using freeform meshes.
  3395.  
  3396. This kind of task where we have to deal with thousands of objects would be
  3397. almost impossible task to do without programming language.
  3398.  
  3399. In this example we will use a SIMPLE SKELETON method to pull the sphere
  3400. mass on the freeform mesh representing a head. RPL is used for creating
  3401. all spheres as well as defining positions for each sphere so that they
  3402. will be scattered all over the head.
  3403.  
  3404. Clear the Settings/Creation/Auto_Index menu. This dramatically speeds up
  3405. the creation process. It might be a good idea to switch the Undo feature
  3406. off.
  3407.  
  3408. Write the following program using your favourite text editor and save it:
  3409.  
  3410.      : CrSpheres ( iHowmany )
  3411.       1 O_LOCK
  3412.       0 DO
  3413.         0 0 0 ( center )
  3414.         0.05 0 0 ( a )
  3415.         0 0.05 0 ( b )
  3416.         0 0 0.05 ( c )
  3417.         255 255 255 0 ( RGBA )
  3418.         "ell" ( name )
  3419.         0 ( flags )
  3420.         "CEND"
  3421.         C_ELLIPSOID
  3422.         NOT IF
  3423.           "Not Enough Memory" PUTS
  3424.            0 O_LOCK
  3425.            EXIT
  3426.         ENDIF
  3427.         I.
  3428.       LOOP
  3429.       0 O_LOCK
  3430.       "Done" PUTS
  3431.      ;
  3432.  
  3433. Now open one RPL window and load the program in. This just defines the
  3434. word CrSpheres.
  3435.  
  3436. As you can see the word CrSpheres takes one parameter which is the number
  3437. of spheres to be created. Depending on the memory available, your can call
  3438. this word with a different amount of spheres. If you have six megabytes of
  3439. RAM memory installed, you should be able to create about 1000 spheres. So
  3440. call the CrSphere as follows:
  3441.  
  3442.      1000 CrSphere
  3443.  
  3444. This creates 1000 spheres.
  3445.  
  3446. Then we have to define the positions of the spheres on the skeleton mesh.
  3447. If you are familiar with the skeleton methods, you know that the tag VPHS
  3448. is used for defining at which position of the skeleton the target object
  3449. in question is pulled. Because we are going to use a freeform mesh (a
  3450. head) as a skeleton object, we have to define the first two components of
  3451. the VPHS tag. For example, if the value 0,0 corresponds to the left top
  3452. edge of the mesh, then the value 1,1 corresponds to the right bottom edge.
  3453. The value 0.5 0.5 corresponds to the middle point of the mesh etc.
  3454.  
  3455.                              - TUTORIAL 7.41 -
  3456.  
  3457. So, write the following program (or just load it in from the rpl
  3458. directory):
  3459.  
  3460.      ( A program scattering spheres evenly )
  3461.      ( over a skeleton mesh )
  3462.      VARIABLE iWidth
  3463.      VARIABLE iHeight
  3464.  
  3465.      : DefPhs ( aParent iWidth iHeight )
  3466.       iHeight!
  3467.       iWidth !
  3468.  
  3469.       O_GETSUB DUP NOT IF
  3470.         "No subobjects" PUTS
  3471.         EXIT
  3472.       ENDIF
  3473.  
  3474.       iHeight @ 0
  3475.       DO
  3476.         iWidth @ 0
  3477.         DO
  3478.           DUP "CEND" I iWidth @ F/J iHeight @
  3479.           F/ 0.0 "VPHS" O_CREATAG
  3480.           NOT IF
  3481.             "Cannot create tag" PUTS
  3482.             EXIT
  3483.           ENDIF
  3484.           "." PUTS
  3485.           O_GETNEXT DUP NOT IF
  3486.             "AII Done" PUTS
  3487.             EXIT
  3488.           ENDIF
  3489.         LOOP
  3490.       LOOP
  3491.      ;
  3492.  
  3493. The word DefPhs takes three parameters: the address of the object
  3494. containing all spheres, the number of spheres in "u" direction and the
  3495. number of spheres in "v" direction. For example, if the Width parameter
  3496. is 100, there will be 100 spheres in the "u" direction of the mesh.
  3497.  
  3498. Now, make the object containing all created spheres the current level
  3499. and enter the following command:
  3500.  
  3501.      O_GETCUR 35 35 DefPhs
  3502.  
  3503. This defines the VPHS tag for each sphere in the current level so that
  3504. each cross-section curve of the head will consist of 35 spheres.
  3505.  
  3506. Create one SIMPLE SKELETON method beside all the spheres and add the
  3507. following tag to it:
  3508.  
  3509.      ISKE 3
  3510.  
  3511. This tells the skeleton method that the VPHS tags are already created and
  3512. are up to date. If you forget to add this tag, the method will
  3513. automatically define tags according to the current positions of the target
  3514. objects.
  3515.  
  3516. Load your freeform mesh representing a head inside the method object. Now
  3517. the hierarchical structure of your object should be as follows:
  3518.  
  3519.            +------+
  3520.            | Root |
  3521.            +------+
  3522.             /    \
  3523.      +--------+ +-------------+
  3524.      | o1..oN | | Skeleton(M) |
  3525.      +--------+ +-------------+
  3526.                          \
  3527.                +---------------+
  3528.                | B-Spline_Head |
  3529.                +---------------+
  3530.  
  3531. So, spheres (o1 ... oN) are pulled on the B-Spline_Head object by the
  3532. skeleton method.
  3533.  
  3534. Your "SphereMan" is now ready. Select the menu Animate/Control/Refresh and
  3535. all the spheres are pulled on the head. Make the skeleton object invisible
  3536. if you don't want to see the mesh itself.
  3537.  
  3538. We will stop here, but you can carry on by animating the skeleton mesh.
  3539. This also causes the spheres to be animated (because whatever you do to
  3540. the head object, the spheres are always pulled on its surface). For
  3541. example, you can add one WAVE method beside the B-Spline_Head and the
  3542. sphere head will wave.
  3543.  
  3544.            +------+
  3545.            | Root |
  3546.            +------+
  3547.             /    \
  3548.      +--------+ +-------------+
  3549.      | o1..oN | | Skeleton(M) |
  3550.      +--------+ +-------------+
  3551.                     /      \
  3552.        +---------------+ +---------+
  3553.        | B-Spline_Head | | Wave(M) |
  3554.        +---------------+ +---------+
  3555.                             /   \
  3556.                       +------+ +-------+
  3557.                       | axis | | curve |
  3558.                       +------+ +-------+
  3559.  
  3560.                              - TUTORIAL 7.42 -
  3561.  
  3562. Now the spheres (o1 ... oN) are pulled on the B-Spline_Head which is
  3563. morphed by the Wave method.
  3564.  
  3565. Or you can use this technique just as a creation tool and delete the
  3566. skeleton after all spheres are pulled on it. Then you can use the sphere
  3567. as a beginning situation in particle animations.
  3568.  
  3569. The possibilities are infinite and the only existing limit is your
  3570. imagination.
  3571.  
  3572.                              - TUTORIAL 7.43 -
  3573.  
  3574. REFERENCE
  3575. ---------
  3576.  
  3577. Chapter 1 MENU FUNCTIONS
  3578. ------------------------
  3579.  
  3580. The following syntax is used to describe all the functions available
  3581. by menu selection:
  3582.  
  3583. / - SUB-MENU ITEMS FOLLOW
  3584.  
  3585. * - TOGGLE GADGET
  3586.  
  3587. 1.1 PROJECT
  3588.  
  3589. The REAL 3D binary file format follows the IFF standard. The various
  3590. data-structures necessary to define a complete REAL 3D project are each
  3591. saved in a different data-section.
  3592.  
  3593. Each data-structure can be saved and loaded independently. For each major
  3594. data-structure type, there is a specific function. In addition, under the
  3595. Project/ sub-menu are functions for loading and saving each individual
  3596. section.
  3597.  
  3598. There are two variants of loading for each data-section: "Insert" which
  3599. loads the new data and adds it to the existing data-structure; and
  3600. "Replace" which clears the existing data-structure if or when it loads
  3601. the new data.
  3602.  
  3603. The loader is intelligent, and can cope with loading files which contain
  3604. some or all data-sections, but each loading function will only try to
  3605. load those sections it is specified to load. The "Replace" variant of the
  3606. loading functions do NOT clear the existing data-structure if the
  3607. specified file does not contain the appropriate data-section.
  3608.  
  3609. The different "Save" functions only save those sections they are specified
  3610. to save.
  3611.  
  3612. All the functions open a file-requester to allow the user to select the
  3613. REAL 3D IFF file to load from. Changing the DOS path updates path-
  3614. settings, so it is remembered by the requester the next time it is used.
  3615.  
  3616. If "Confirm Save" gadget is set by using Settings/General requester, the
  3617. user is asked to confirm the operation before the old file is overwritten.
  3618.  
  3619. When working on a Workbench(TM) screen, Real-IFF files can also be loaded
  3620. by moving their icons onto a View window.
  3621.  
  3622. Objects/
  3623.  
  3624. Insert
  3625. Load new objects from specified file into the current level of hierarchy.
  3626.  
  3627. Save
  3628. Save selected objects to the specified file,
  3629.  
  3630. Replace
  3631. Clears the hierarchy if/when it loads the object section of the specified
  3632. file.
  3633.  
  3634. Project/
  3635.  
  3636. The user is presented with a requester to define the new name for the root
  3637. object.
  3638.  
  3639. New
  3640. This does the following:
  3641.  
  3642. 1. Hierarchy cleared
  3643. 2. Material Library deleted
  3644. 3. Named Colors Library deleted
  3645. 4. Grid Definitions removed
  3646. 5. Vector stack is cleared
  3647. 6. Undo Buffer cleared
  3648. 7. Time and Frame Count are reset to zero
  3649.  
  3650.                              - REFERENCE 1.1 -
  3651.  
  3652. Insert
  3653. Load all the available sections of a project definition from the specified
  3654. file.
  3655.  
  3656. Save
  3657. Saves all sections of the current project definition to specified file.
  3658.  
  3659. Replace
  3660. Load all available sections from the IFF file and delete any corresponding
  3661. data structures in memory.
  3662.  
  3663. Insert Sections
  3664. A requester is opened to allow only those sections of a REAL 3D file the
  3665. user selects to be loaded. After the selection has been confirmed, the
  3666. file requester will be opened.
  3667.  
  3668. Save Sections
  3669. Opens requester to select data sections for saving, then the file
  3670. requester.
  3671.  
  3672. Replace Sections
  3673. Opens data sections requester for selecting the sections to replace from
  3674. a file.
  3675.  
  3676. Materials/
  3677.  
  3678. Material definitions are stored in the material library. They are created
  3679. and modified using a material window.
  3680.  
  3681. Window
  3682. Open a Material editor window. This allows materials to be created and
  3683. modified while other actions, in particular rendering, are taking place.
  3684.  
  3685. The material definitions are stored in a material data structure, called
  3686. the material library, complete with their material name, The material
  3687. definitions are created and modified using a material editor window.
  3688.  
  3689. Figure R1-1: Material Editor Window  (PICTURE: R1-1)
  3690.  
  3691.                              - REFERENCE 1.2 -
  3692.  
  3693. Local Menu:
  3694.  
  3695. DEFINE/
  3696.  
  3697. Texture <RAM>D
  3698. Select name of image file using file requester.
  3699.  
  3700. Show Texture <RAM>S
  3701. Display image file. If the image is 24 bit and the External screen is
  3702. open, then a requester will be produced asking for confirmation, as
  3703. displaying the image may overwrite the contents of the External screen.
  3704.  
  3705. Trans. Color <RAM>C
  3706. Select Transparent color from current color.
  3707.  
  3708. Tags<RAM>T
  3709. Open the Tag requester to modify or define the tags associated with the
  3710. current material.
  3711.  
  3712. Gadgets of the Material window:
  3713.  
  3714. Name
  3715. Name of material in the Material library.
  3716.  
  3717. Texture
  3718. The path and name of an image file to use for defining various material
  3719. properties like color or transparency. Each pixel in the bit-map relates
  3720. to a point on the surface of the object, depending upon the type of
  3721. mapping control object associated with the material and its position
  3722. relative to the physical object, An index format string can be included
  3723. as part of the name. This means that the value of the index variable "i"
  3724. will be formatted to this specification and included as part of the file
  3725. name.
  3726.  
  3727. Spline
  3728. When this gadget is set, and the target object for the material is a
  3729. B-spline mesh, then the object itself is used for the mapping definition.
  3730. Any coordinate transformations defined by mappings associated with the
  3731. material are ignored. This means that the mapping of the texture file
  3732. follows any modifications to the shape of the mesh.
  3733.  
  3734. S-map uvwh
  3735. These four numeric gadgets control the position and size of the image file
  3736. when it is mapped onto a spline. The u and v values determine the position
  3737. of the top left corner of the image and w and h control what proportion of
  3738. the spline is covered. Each of these can be between 0.0 and 1,0,
  3739.  
  3740. Color map
  3741. Texture is to be used for material color definition.
  3742.  
  3743. Bump map
  3744. Red component of texture is used for bump map evaluation. The brighter the
  3745. red component, the higher the bump.
  3746.  
  3747. Transparency map
  3748. Green component is used for transparency evaluation. The brighter the
  3749. green component, the more transparent the material.
  3750.  
  3751. Brilliance map
  3752. Blue component is used for evaluating brilliance. The brighter the blue
  3753. component, the more mirrorlike the material.
  3754.  
  3755. Shadow map
  3756. The RGB values of each pixel of the texture file are used to modify the
  3757. current color values for the corresponding point of the objects surface,
  3758. The modification formula is:
  3759.  
  3760.      R*r/255, G*g/255 & B*b/255
  3761.  
  3762. Where: r, g, b are the color values of the pixel and R, G, B are the
  3763. current color values of the surface point
  3764.  
  3765. It is intended for this function to be used with grayscale texture files
  3766. to artificially produce shadow effects as an alternative to using Render
  3767. Settings/Normal mode or , when it is necessary, to create artificial
  3768. shadows in addition to rendered ones.
  3769.  
  3770. Note:
  3771. If shadow mapping is used with a pure white object, it produces the same
  3772. results as color mapping.
  3773.  
  3774.                              - REFERENCE 1.3 -
  3775.  
  3776. Clip map
  3777. The surface of the object is clipped by the texture file. The object
  3778. surface is removed wherever it is not covered by the texture file. This
  3779. includes any areas not covered by the mapping or tiling, or any areas
  3780. selected as transparent.
  3781.  
  3782. Scope mask
  3783. If this gadget is set, the material effect is modified by using the
  3784. texture as a mask, which defines where the material is applied. Only the
  3785. points which are affected by the texture, included in the material, get
  3786. non-zero scope. The application test is equivalent to the one used for
  3787. clip mapping.
  3788.  
  3789. Transparent Color (Transp. col)
  3790. The color to use as the transparent color is taken from the numeric
  3791. gadgets: Trans.R, Trans.G, and Trans.B. This affects the application of a
  3792. texture for clip mapping and scope mask. Transparent color is defined in
  3793. 24-bit color space, so all values vary between 0 and 255. You can
  3794. translate a color in original Amiga color system, values ranging from 0 to
  3795. 15, to 24-bit system by multiplying each color component value by 16. For
  3796. example, pure white R=15,G=15,B=15 corresponds R=240, G=240, B=240.
  3797.  
  3798. Unshaded
  3799. Light sources and shadows do not affect the shading of this material.
  3800.  
  3801. Smooth
  3802. Removes specular reflections on the boundaries of transparent materials.
  3803.  
  3804. Exclusive
  3805. When the rendering engine evaluates the material properties for each point
  3806. on a surface, it mixes all the properties for each material defined by the
  3807. mappings at the same hierarchical level. If only one mapping is present,
  3808. then the material properties are mixed with the default material
  3809. properties.
  3810.  
  3811. Setting the Exclusive property means that other material definitions are
  3812. ignored for any points on the surfaces covered by that specific material.
  3813. See Also: "Effect" and "Scope" in this sub-chapter.
  3814.  
  3815. Tiling Gadgets
  3816.  
  3817. Tile
  3818. Selects whether texture file is to be tiled in X, Y or both directions.
  3819.  
  3820. Flip
  3821. Selects whether tiled texture file is to be mirrored in X, Y or both
  3822. directions. If set, then every second tile is flipped, making texture map
  3823. edges match better.
  3824.  
  3825. X-Freq. & Y-Freq.
  3826. These numeric gadgets specify the number of tiling repetitions over the
  3827. surface of the texture. If the frequency is set to 0, the texture is tiled
  3828. infinitely for all mapping types, except spherical mapping. For parallel,
  3829. both X & Y can be infinitely tiled; and for cylindrical and disk mapping,
  3830. only Y = 0 is treated as infinite tiling. When infinite tiling is used,
  3831. each tile is the size of the texture along that axis.
  3832.  
  3833. Grade
  3834. Selects whether color gradients are calculated for X, Y or both directions
  3835. of the texture file. Color gradients produce smooth transitions from the
  3836. color of one pixel to the color of the adjacent pixels.
  3837.  
  3838. Specularity
  3839. Controls how sharply defined are the high-lights reflected from the
  3840. surface of the material by light sources. The higher the specularity, the
  3841. smaller the high-light and the harder its edges.
  3842.  
  3843. Specular brightness (Spec. bright.)
  3844. This affects how intense the specular high-lights are.
  3845.  
  3846. Brilliance
  3847. The degree to which light is reflected directly from the material surface
  3848. ("mirror-like" property),
  3849.  
  3850. Transparency
  3851. The degree to which light passes through the material surface.
  3852.  
  3853.                              - REFERENCE 1.4 -
  3854.  
  3855. Turbidity
  3856. Controls the degree to which light is affected as it passes through the
  3857. material. The higher the setting the denser the "fog".
  3858.  
  3859. Turbidity saturation (Turbid. sat.)
  3860. Defines how the distance which light travels in a turbid material affects
  3861. the light. The default value 25 gives a linear result; so if the distance
  3862. is doubled, then the effect is doubled. If this value is zero, then the
  3863. distance has no effect at all. The actual equation is:
  3864.  
  3865.      "turbidity effect" = Turbidity *
  3866.      (distance^Turbid. sat.),
  3867.      ^ = to the power of
  3868.  
  3869. Refraction
  3870. This determines the degree to which light is bent as it passes through the
  3871. material. It represents the speed of light in the material as a percentage
  3872. of its maximum speed through empty space. The higher this value the less
  3873. the light is bent.
  3874.  
  3875. Roughness
  3876. This controls the degree of "molecular texture" applied by the material.
  3877. This "molecular" texture is a random bump-map which is independent of
  3878. the magnification of the material.
  3879.  
  3880. Dither
  3881. This enables dithering of material color to be applied to individual
  3882. objects and the precise amount of dithering to be selected. The actual
  3883. amount of color deviation applied is given by:
  3884.  
  3885.      R = R + rnd,
  3886.      G = G + rnd,
  3887.      B = B + rnd where -di/2 < rnd < di/2
  3888.  
  3889. where: di is the dither setting.
  3890.  
  3891. Bump height
  3892. Relative scale of bumps produced by bump-mapping texture file and
  3893. procedural bump handler.
  3894.  
  3895. Effect
  3896. All materials at the same hierarchical level are mixed together. This
  3897. controls how strongly the properties of the current material will affect
  3898. the objects to which it is applied. Effect level is combined with the
  3899. Scope material variable "s" to determine the final strength of the
  3900. material properties at any point on the surface of the targets.
  3901.  
  3902. APPLY
  3903. Apply the current settings to the library under the name specified in the
  3904. "Name" text-gadget. If a material under the name already exists, the old
  3905. definition is overwritten. Otherwise a new material is created and
  3906. appended to the material library.
  3907.  
  3908. LOAD
  3909. Open a requester to allow one of the materials in the current material
  3910. library to be selected and loaded into the editor window.
  3911.  
  3912. RESET
  3913. Reset the material editor to display default material properties.
  3914.  
  3915. Procedural Handlers
  3916.  
  3917. In addition to being defined by a slider value or an IFF file, certain
  3918. material properties can be defined using mathematical equations. These
  3919. handlers are modifiers to the properties defined by the other settings.
  3920.  
  3921. The equations to control these properties can come from several sources:
  3922.  
  3923. Default
  3924. No procedural handler.
  3925.  
  3926. Formula
  3927. An equation with an assignment to a system variable is entered in the
  3928. expression box. This expression is evaluated using the RPL word EVAL.
  3929.  
  3930.                              - REFERENCE 1.5 -
  3931.  
  3932. RPL
  3933. RPL text is used to define the handler. This can either take the form of
  3934. direct RPL words and operands, or an external RPL file to be loaded.
  3935. The RPL text is interpreted, so the fastest way to implement any handler
  3936. is to define an RPL word which accesses the material variables directly.
  3937. The name of this word is then entered into the expression box as the RPL
  3938. text. The text is interpreted by the RPL "Master" environment, so if the
  3939. word was defined in an RPL window, then it is necessary for "Master" to
  3940. INHERIT the other environment. For more details of this see RPL
  3941. documentation.
  3942.  
  3943. Built-in Handlers
  3944. Each procedural handler has several built-in formulas to produce
  3945. particular effects more rapidly than using the equivalent as a Formula
  3946. or RPL handler. These handlers use the a and b variables as control
  3947. parameters for various aspects of their formulas. The default value for
  3948. both a and b is usually 1.0, but Scope and Color/Waves are exceptions. For
  3949. the Scope handlers, the default for a is Material Variable sz, the texture
  3950. size, which is used if a = 0.0. In the Color/Waves handler, the default
  3951. for b is 128.
  3952.  
  3953. Descriptions
  3954.  
  3955. The equivalent formula for each of these handlers are given under the
  3956. heading for the handler type to which they apply. The formulas use w for
  3957. the texture map width and h for texture map height, but these are not
  3958. material variables.
  3959.  
  3960. Material Variables
  3961.  
  3962. a,b - User definable variables, initially assigned the value of the
  3963.       numeric gadgets to the right of the expression gadget.
  3964. x   - Horizontal texture coordinate.            Type: FLOAT
  3965. y   - Vertical texture coordinate.              Type: FLOAT
  3966. z   - Depth texture coordinate.                 Type: FLOAT
  3967. sz  - Size of texture geometry.                 Type: FLOAT
  3968. r   - Distance from the origin of the texture.  Type: FLOAT
  3969. s   - Scope output variable.                    Type: FLOAT
  3970. sp  - specularity                               Type: FLOAT
  3971. sb  - specular brightness                       Type: FLOAT
  3972. br  - brilliance                                Type: FLOAT
  3973. tr  - transparency                              Type: FLOAT
  3974. tu  - turbidity                                 Type: FLOAT
  3975. ts  - turbid saturation                         Type: FLOAT
  3976. ri  - refraction index                          Type: FLOAT
  3977. ro  - roughness                                 Type: FLOAT
  3978. di  - dithering scale                           Type: FLOAT
  3979. bh  - bump height                               Type: FLOAT
  3980. bx  - Bump-map horizontal coefficient           Type: FLOAT
  3981. by  - Bump-map vertiCal coefficient             Type: FLOAT
  3982. R   - Red color component                       Type: INTEGER
  3983. G   - Green color component                     Type: INTEGER
  3984. B   - Blue color component                      Type: INTEGER
  3985. t   - Local animation time                      Type: FLOAT
  3986. i   - Material texture index                    Type: INTEGER
  3987.  
  3988.                              - REFERENCE 1.6 -
  3989.  
  3990. The following variables are available as a part of EVAL's function:
  3991.  
  3992. Frm - Current Frame index                       Type: INTEGER
  3993. Res - Frame Resolution                          Type: INTEGER
  3994. T   - Global animation time                     Type: FLOAT
  3995.  
  3996. The ranges of x & y are either between 0,0 and 1,0 if no texture mapping
  3997. type is being used, or between zero and the number of pixels along the x
  3998. or y dimension of the texture file.
  3999.  
  4000. z, sz & r are distances expressed in spatial coordinates and can have any
  4001. positive value,
  4002.  
  4003. If the mapping used is type Default, then x, y & z are the absolute
  4004. spatial coordinates, and any mathematical handlers will effectively use
  4005. Parallel mapping along z-axis.
  4006.  
  4007. The value sz depends on the texture geometry in the following way:
  4008.  
  4009. parallel - length of the shorter texture rectangle edge
  4010. cylinder - radius of the cylinder (average if elliptic)
  4011. sphere   - radius of the sphere (average if elliptic)
  4012. disk     - radius of the disk (average if elliptic)
  4013.  
  4014. The values for R,G & B are from 0 to 255. If a user defined formula
  4015. assigns a value greater than 255, then it will be limited to 255.
  4016. Negative values become zero.
  4017.  
  4018. The range for T & t is between 0.0 and 1.0.
  4019.  
  4020. The value of i is assigned by the user and can have any integer value.
  4021.  
  4022. Frm & Res are a positive integer values between 0 and MAX_INT
  4023.  
  4024. All the others should be between 0,0 and 100.0. If a formula takes a
  4025. variable outside this range, then the effects are unpredictable.
  4026.  
  4027. The order of the handlers indicates the order in which they are evaluated;
  4028. Mapping first and Index last.
  4029.  
  4030. Although the material variables can be assigned values at any time,
  4031. assigning them values before the handler in which they are properly
  4032. assessed has no practical effect, e.g. The color components are assigned
  4033. their values from the texture file after the evaluation of the mapping and
  4034. scope. The material variables x,y & z can be modified in any of the
  4035. expressions,
  4036.  
  4037. Handler Types:
  4038.  
  4039. Mapping
  4040.  
  4041. Material Variables: x, y & z.
  4042.  
  4043. The Mapping handler is evaluated after the initial coordinate
  4044. transformation calculations that use the mapping geometry have evaluated
  4045. the values of x,y & z. Using an equation to modify one of these variables
  4046. changes the way in which a texture file is mapped onto the surface.
  4047.  
  4048. The following diagram shows how the mapping axes relate to the geometry
  4049. of each mapping type. The x, y, z coordinates in the diagram relate
  4050. directly to the material variables.
  4051.  
  4052.                              - REFERENCE 1.7 -
  4053.  
  4054. Figure R1-2: Mappings  (PICTURE: R1-2)
  4055.  
  4056. Built-in Handlers
  4057.  
  4058. Tilt y = y + x*a*h/w
  4059. Waves y = y + sin(x*a*PI/w)*b*h
  4060. SwapXY tmp = x, x = y, y = tmp
  4061.  
  4062. Scope
  4063.  
  4064. Material Variables: s, sp, sb, br, tr, tu, ts, ro, ri
  4065.  
  4066. The primary variable for the scope handler is "s" which, along with Effect
  4067. level, determines how much of the material properties are mixed with the
  4068. material properties already applied to the objects. If no other materials
  4069. are applied, then the material is mixed with the default properties.
  4070.  
  4071. Built-in Handlers
  4072.  
  4073. Sphere if r < a s=100, else s=0
  4074. InvLin s = 100/(1 + r^2/a)
  4075. InvExp s = 100*exp(-r/a)
  4076. Local s = max(100*a/(a-r),0)
  4077. Temporal s = s*(a*(1 - T) + b*T)
  4078.  
  4079. Where a = sz by default, except in Temporal, where a = 1 by default.
  4080.  
  4081. Bump
  4082.  
  4083. Material Variables: bh, bx & by.
  4084.  
  4085. Bump-mapping is a process whereby the surface normal produced by the ray
  4086. hit routines of the rendering engine are modified to make the surface
  4087. appear to have "ripples" or "bumps". This modification is carried out by
  4088. using vector addition between the true normal and two other vectors.
  4089.  
  4090. The variables bx & by define the vectors used to deviate the normal and
  4091. produce the bump-mapping effect. If a texture file is being used as a
  4092. bump map, then bx and by are first evaluated from the red component of
  4093. the texture.
  4094.  
  4095.                              - REFERENCE 1.8 -
  4096.  
  4097. The bump-mapping vectors and their relationship to the normal (denoted by
  4098. n) are illustrated in the following diagram:
  4099.  
  4100. Figure R1-3: Bump Variables in Mappings  (PICTURE: R1-3)
  4101.  
  4102. Built-in Handlers
  4103.  
  4104.      Waves bx = bx + sin(x*a*PI/w)*b
  4105.      Bumps bx = bx + sin(x*a*PI/w)*b, by = by + sin(y*a*PI/h)*b
  4106.  
  4107. Color
  4108.  
  4109. Material Variables: R, G & B.
  4110.  
  4111. The color components of the material can also be mathematically modified.
  4112. The initial values for R,G & B are evaluated from the texture file if
  4113. used. Mathematical formulas can then be used to modify or replace these
  4114. initial values, as with the other Material Variables. The size variable
  4115. (sz) can be used for to bind a formula to the size of a texture.
  4116.  
  4117. Built-in Handlers
  4118.  
  4119.      Bright R = R*b/(r*a + 1.0) ( G,B similar )
  4120.      Waves R = R + sin(x*a*w/h)*b ( G,B similar )
  4121.  
  4122. Index
  4123.  
  4124. Material Variable: i
  4125.  
  4126. The material variable i is evaluated by any index format string used in
  4127. the texture file name. Using a mathematical formula based upon either T, t
  4128. or Frm makes it possible to control the indexes of texture files in very
  4129. flexible ways to create moving material textures.
  4130.  
  4131. Built-in Handlers
  4132.  
  4133.      Default i = a, a+1, ..., b-1, 0, 1, ..., b-1, ...
  4134.      PingPong i = a, a+1, ..., b-1, b-1, b-2, ..., 0, 1, ...
  4135.  
  4136. Index handler default values are a = 0.0, b = 0.0 (zero offset and no
  4137. modulo cycle).
  4138.  
  4139.                              - REFERENCE 1.9 -
  4140.  
  4141. Non-homogeneous Material Properties
  4142.  
  4143. By using the procedural handlers, or mixing multiple materials, certain
  4144. material properties can be evaluated non-uniformly, so the properties vary
  4145. with their depth in the material. The number of times the material
  4146. properties are sampled is dependent upon Render Settings/Mat. samples.
  4147. The following properties, and their corresponding Material Variables are
  4148. evaluated in this way:
  4149.  
  4150.      specularity
  4151.      specular brightness
  4152.      turbidity
  4153.      turbid saturation
  4154.  
  4155. These non-homogeneous materials enable atmospheric gasses and sun-glow
  4156. effects to be created.
  4157.  
  4158. Delete
  4159.  
  4160. Open a requester allowing the user to select a material from the library
  4161. for deletion.
  4162.  
  4163. If mappings still refer to deleted materials, then default material is
  4164. used, If a new material with the same name is created or loaded, then the
  4165. mappings will use the new definition.
  4166.  
  4167. Delete All
  4168.  
  4169. Delete all material definitions from the material library,
  4170.  
  4171. Insert
  4172.  
  4173. Load previously saved material definitions into material library.
  4174.  
  4175. Save
  4176.  
  4177. Save all material definitions in material library to the specified file.
  4178.  
  4179. Replace
  4180.  
  4181. Material library is cleared if the specified file contains a material
  4182. section and new materials are loaded.
  4183.  
  4184. Macros/
  4185.  
  4186. Macros are files containing the ASCII text of the operands and RPL words
  4187. which recreate the actions of the user. Hierarchical selection is not
  4188. recorded, so the macro executes using the selected objects as operands.
  4189. The current macro is saved in the file t:macro.rpl. Only those actions
  4190. which modify objects or the hierarchy structure are recorded. As well as
  4191. being executed by the functions below, macros can be executed from an RPL
  4192. window using the "LOAD" word.
  4193.  
  4194. The RPL system saves and executes macro files on a line by line basis.
  4195. This means the only limit to the size of a macro is the OS maximum file
  4196. size.
  4197.  
  4198. * Record Macro
  4199.  
  4200. Record all user selected functions and input data as the current macro.
  4201. When macro recording is started, the previous current macro is deleted.
  4202.  
  4203. Execute Current
  4204.  
  4205. Execute current macro upon the selected objects. This is equivalent to
  4206. executing the RPL command t:macro.rpl LOAD.
  4207.  
  4208. Execute Named
  4209.  
  4210. Produces file requester for user to select name of stored RPL text file.
  4211. This is usually a macro, but it could be any executable file. The selected
  4212. file is then executed in the "Master" RPL environment.
  4213.  
  4214.                             - REFERENCE 1.10 -
  4215.  
  4216. Repeat Current
  4217.  
  4218. Execute current macro specified number of times. This is implemented
  4219. internally using following RPL code:
  4220.  
  4221.      : Repeat_Current
  4222.       n 0 DO
  4223.         t:macro.rpl LOAD
  4224.       LOOP
  4225.      ;
  4226.  
  4227. where n is the number of repetitions requested by the user.
  4228.  
  4229. Spread Current
  4230.  
  4231. Executes the current macro upon selected objects increasing execution
  4232. count by one for each consecutive object. The execution count starts from
  4233. zero, so it is not executed at all for the first object, then once for
  4234. the second and twice for the third.
  4235.  
  4236. Current to Named
  4237.  
  4238. Opens a File Requester to the Macro Directory allowing user to define a
  4239. new name for the current macro. This does not affect the operation of the
  4240. current macro. This is the equivalent to copying the macro file using the
  4241. OS.
  4242.  
  4243. Named to Current
  4244.  
  4245. Opens file requester allowing the user to select the macro file to be
  4246. copied to the current macro file. This can also be accomplished using OS
  4247. file copying.
  4248.  
  4249. Named Colors/
  4250.  
  4251. Named colors are a way of storing special colors which need to be used
  4252. repeatedly and on different projects. The color values of these colors are
  4253. saved in a library which can be saved to a file, then re-loaded at a later
  4254. date.
  4255.  
  4256. Select
  4257.  
  4258. A color is selected from the named colors library using a requester. The
  4259. value of the current color will assume the value of the named color
  4260. selected.
  4261.  
  4262. Create
  4263.  
  4264. The RGB values of the current color are saved in the named colors library
  4265. under the name specified.
  4266.  
  4267. Modify
  4268.  
  4269. A named-color is selected from the library and its RGB values are changed
  4270. to those of the current color.
  4271.  
  4272. Delete
  4273. The selected color is deleted from the library.
  4274.  
  4275. Insert
  4276.  
  4277. Load the file specified into the Named colors library. The existing named
  4278. colors are not replaced.
  4279.  
  4280. Save
  4281.  
  4282. Save the Named colors library as the file specified,
  4283.  
  4284.                             - REFERENCE 1.11 -
  4285.  
  4286. Replace
  4287.  
  4288. Replace the Named colors library if the file specified contains
  4289. appropriate data section.
  4290.  
  4291. Windows/
  4292.  
  4293. Most windows are opened on the default public screen unless they are too
  4294. large, when they will be opened on another public screen which is large
  4295. enough. The animation window and palette window each open on their own
  4296. private screens, which take their Interlace/Non-Interlace properties from
  4297. the default public screen.
  4298.  
  4299. Select
  4300.  
  4301. Open window for selecting objects and moving through the hierarchy.
  4302. Clicking on individual names selects a single object. Using <DRAG> over
  4303. the Select window multi-selects objects. To de-select objects use
  4304. <LMB><SHIFT> or <DRAG><SHIFT>.
  4305.  
  4306. The Select window uses the following text styles to indicate which types
  4307. of objects are in the hierarchy:
  4308.  
  4309.      - Normal style used for primitives.
  4310.      - Bold style used for levels.
  4311.      - Italic used for controls and mappings.
  4312.  
  4313. The current level is shown at the top left of the select window. All the
  4314. objects in that level are indented and arranged in their order in the
  4315. hierarchy from first to last.
  4316.  
  4317. - Methods are shown with "(M)" after their name, unless they are the
  4318.   current level, when their method type will be shown in full.
  4319. - A level with the boolean operator "AND" is shown with "(A)" after its
  4320.   name.
  4321. - In addition to being printed in italics, mappings have "(T)" as a
  4322.   postfix to their name.
  4323.  
  4324. The purpose of the select window is to show the logical structure of the
  4325. object and to make it possible to point objects through their names.
  4326.  
  4327. View
  4328.  
  4329. Open a general purpose View which is the window into the REAL 3D universe.
  4330. Individual Views can be configured using the functions in the View menu.
  4331. Each View stores all its own settings, including both the sizes and
  4332. positions selectable with the "zoom-gadget" to the right of the "depth-
  4333. gadget".
  4334.  
  4335. When the Select window shows the logical structure of objects, the View
  4336. window is used for showing the physical structure of objects.
  4337.  
  4338. The operation of View windows is part of the asynchronous design of REAL
  4339. 3D. This means that they take full advantage of the Amiga multi-tasking
  4340. environment by executing time consuming functions, like rendering, as a
  4341. separate "task". This task will continue to run in the background, leaving
  4342. the View free to respond to all user actions promptly.
  4343.  
  4344. View Superbitmap
  4345.  
  4346. Open superbitmap View, This means the window can be moved over a much
  4347. larger "virtual" View using the scroll-bars at the bottom and right
  4348. side. Objects can be created and modified, even rendered on any part of
  4349. the superbitmap.
  4350.  
  4351. View Borderless
  4352.  
  4353. Open View covering the full screen. This has no visible borders and
  4354. obscures the menu-strip. This window type is usually needed for rendering
  4355. final images or animations where window borders are not desirable.
  4356.  
  4357. View DBuffered
  4358.  
  4359. Opens a double-buffered borderless View on a new screen. This enables
  4360. wire-frame motion to be observed without seeing the intermediate drawing
  4361. steps, so the image does not flicker. The new screen is always 4 color,
  4362. 640 wide, maximum height and interlaced. This screen is
  4363.  
  4364.                             - REFERENCE 1.12 -
  4365.  
  4366. a special private screen and no other windows can be opened on it. By
  4367. default the View projection type is perspective.
  4368.  
  4369. RPL
  4370.  
  4371. Open RPL Shell window for programming RPL words. This is an OS Shell
  4372. window with support for all the editing, text history and clipboard
  4373. hot-keys (<RAM>c and <RAM>v). It has no menu strip associated with it.
  4374.  
  4375. RPL window is designed for interactive use. Henceforth each RPL window has
  4376. its own environment where all RPL definitions are private to the window
  4377. in question and cannot be accessed by other windows unless parent/child
  4378. relationship is established using inheritance.
  4379.  
  4380. All defined words, variables etc. also disappear when the window is
  4381. closed. When more permanent definitions are desired, the Master
  4382. environment can be used for that purpose and, when necessary, RPL windows
  4383. can inherit Master's RPL context by executing the command Master INHERIT
  4384. RPL words, variables etc. can be defined to the master's RPL environment
  4385. by loading them as macros, sending them through the ARexx port or defining
  4386. them in the "rpl-startup" file. The Master RPL environment is allocated
  4387. when REAL 3D is started and it is used for executing macros, ARexx
  4388. commands and requester formula evaluation.
  4389.  
  4390. Tool
  4391.  
  4392. Open Tool window for loading with tool icons. There are a number of pre-
  4393. defined tool icons in the REAL 3D system, and these provide single-click
  4394. short-cuts to selecting the most frequently used creation and modification
  4395. functions. The user can also create his own icons using Tool/Create Icon.
  4396. These icons can invoke any executable RPL file or RPL word.
  4397.  
  4398. The purpose of Tool window is to provide the user with ability to expand
  4399. and customize the user interface of the program to suit different kinds of
  4400. projects. Tool windows have no separate RPL environment, so in order to
  4401. bind icons to RPL words, the word must be defined in Master's RPL
  4402. environment. If the icon is bind to a file, the RPL file must be found
  4403. from the macros directory specified in Settings/Paths.
  4404.  
  4405. Animation
  4406.  
  4407. Open Animation window on its own private Hires screen.
  4408.  
  4409. The animation window is used for controlling the animation system, for
  4410. defining animation settings such as the number of frames to be used for
  4411. rendering an animation and the name of the result file.
  4412.  
  4413. Figure R1-4: Animation Window  (PICTURE: R1-4)
  4414.  
  4415.                             - REFERENCE 1.11 -
  4416.  
  4417. Gadgets of Animation Window:
  4418.  
  4419. Time
  4420.  
  4421. The slider gadget and its associated numeric gadget provide the user with
  4422. an interactive way of altering the global time. The affect of changing the
  4423. time, with either the slider or by entering it numerically, depends on the
  4424. state of the Play To/Jump To gadget.
  4425.  
  4426. Play Controls
  4427.  
  4428. These "video recorder" style controls have the following functions:
  4429.  
  4430. |<...  - Play backwards from current time to time 0.0
  4431.  
  4432. ..>|   - Play forwards to time 1.0
  4433.  
  4434. |<-    - Go to time 0.0
  4435.  
  4436. ->|    - Go to time 1.0
  4437.  
  4438. <.     - Single step one interval backwards
  4439.  
  4440. .>     - Single step one interval forwards
  4441.  
  4442. CANCEL - Cancel all animation processing including rendering
  4443.  
  4444. Play To/Jump To
  4445.  
  4446. This gadget alters the way the Animation System reacts to changes to the
  4447. time gadgets. If "Play To" is selected, then changing the time causes the
  4448. animation to play from the current time to the new time. If "Jump To" is
  4449. selected, then the display is just updated for the new time.
  4450.  
  4451. Screens & Saved
  4452.  
  4453. The list selector enables the one of the open REAL 3D screens to be
  4454. selected for saving to an IFF file after each animation frame. The name
  4455. can also be typed directly into the Saved text gadget. If an External
  4456. screen has been opened, then it can be selected and will be saved using
  4457. the file settings selected with Project/External_Screen/Settings.
  4458.  
  4459. Resolution & Smpl (Samples)
  4460.  
  4461. Resolution controls how many intervals time is divided into when it is
  4462. evaluated from 0.0 to 1.0. Each step is evaluated internally with
  4463. additional intervals set by Samples. Increasing Samples improves the
  4464. quality of particle method evaluation. Samples is also used to determine
  4465. the number of intervals over which to evaluate Motion Blur.
  4466.  
  4467. Frame
  4468.  
  4469. The current frame number. This value increase by one for every interval
  4470. into which Time is divided by Resolution as the animation is saved.
  4471. You can also use the gadget to move in time by entering the corresponding
  4472. time value.
  4473.  
  4474. Seconds
  4475.  
  4476. The value in this field is only used by the Particle animation system to
  4477. determine the amount of real time to evaluate particle movement properties
  4478. over. This means that a particle with a velocity of 1.0 will travel 1.0
  4479. ASCs in 1.0 real time seconds; the evaluation of spin is treated in a
  4480. similar way. Increasing "Seconds" increases the amount of motion for each
  4481. particle during the whole animation.
  4482.  
  4483. Format
  4484.  
  4485. This is an index format string which is used to format the current Frame
  4486. number before appending it to the end of Screen file text, Individual
  4487. Views, which are also handles to files, use the formatted index for their
  4488. file saving.
  4489.  
  4490. Save
  4491.  
  4492. If set, then the selected screen is saved to file and Frame is
  4493. incremented, after rendering of the current frame is completed.
  4494.  
  4495. Screen File
  4496.  
  4497. The name and path for the screen image files saved by the Animation
  4498. system.
  4499.  
  4500.                             - REFERENCE 1.14 -
  4501.  
  4502. Frame Cmd
  4503.  
  4504. This can contain RPL text which is interpreted by the "Master" RPL
  4505. environment every time Frame is incremented. By using the RPL word
  4506. "SYSTEM", commands can be passed to the CLI to control, for example, a
  4507. single-frame video recorder system. Or alternatively, the frame command
  4508. can for example convert IFF images the renderer produces to the JPEG
  4509. format.
  4510.  
  4511. Palette
  4512.  
  4513. Open Palette window. This is opened on its own private HAM screen. The
  4514. Palette is used to control the R,G,B values of the current color and the
  4515. 16 register color values. The current color is used whenever REAL 3D
  4516. requires a color value for a function e.g. Modify/Properties/Color.
  4517.  
  4518. Figure R1-5: Palette Window  (PICTURE: R1-15)
  4519.  
  4520. The register colors give the user fast access to 16 different color
  4521. definitions. Selecting one of the register color buttons makes the current
  4522. color the same as the current value of the register color. The value of
  4523. the register color is then changed using either the sliders or selecting
  4524. from the color spectrum with the left mouse button. Holding the left
  4525. button down while moving over the color spectrum changes the current color
  4526. and the slider values continuously. There is no need to confirm these
  4527. changes. The effects take place when the "OK" gadget is pressed. It is
  4528. also necessary to select the settings required BEFORE using a function
  4529. which uses the current color. If a Palette window is not currently open,
  4530. then the last setting for the current color will be used.
  4531.  
  4532. Measuring
  4533.  
  4534. This opens the Measuring system window. The Measuring system can be used
  4535. for replacing the mouse when accurate input is needed. It also allows the
  4536. user to define coordinates using natural units, such as meters and feet,
  4537. instead of just plain absolute space coordinates.
  4538.  
  4539. Figure R1-6: Measuring Window  (PICTURE)
  4540.  
  4541.                             - REFERENCE 1.15 -
  4542.  
  4543. Measuring window gadgets:
  4544.  
  4545. X, Y, Z
  4546.  
  4547. These gadgets show the current position of the mouse in current units. The
  4548. user can also enter coordinates through these gadgets, in which case the
  4549. effect is the same as if the user moved the mouse to the corresponding
  4550. point in View window. Formula evaluation is also supported, making it
  4551. possible to enter formulas instead of coordinate values.
  4552.  
  4553. The purpose of these gadgets depends on the measuring type used. If
  4554. "Normal" method is used, these fields define 3D coordinate values relative
  4555. to input-plane/absolute space and origin/hotpoint depending on the state
  4556. of other gadgets on the window. If "Polar" is used, X and Y fields define
  4557. the direction (horizontal and vertical angle) and Z field is used for
  4558. distance. Polar coordinates can also be relative to hot-point/origin and
  4559. input-plane/absolute space. The direction is always defined in degrees.
  4560.  
  4561. N
  4562.  
  4563. The purpose of this gadget varies from one function to another. It can be
  4564. used for defining angles for sector primitives, depths for primitives etc.
  4565.  
  4566. Absolute/I-plane (Input-plane)
  4567.  
  4568. This radio button defines whether the coordinates are relative to the
  4569. Input Plane or Absolute Space.
  4570.  
  4571. Normal/Polar
  4572.  
  4573. This radio button defines whether to use normal 3D coordinate system or
  4574. polar (angle&radius) coordinates.
  4575.  
  4576. Origin/Hot-point
  4577.  
  4578. This radio button defines whether to use coordinates relative to origin
  4579. of absolute space or to hot-point.
  4580.  
  4581. Unit
  4582.  
  4583. The cycle gadget defines the unit to be used. The absolute space units
  4584. corresponds to meters. Possible choices are:
  4585.  
  4586.      Symbol  Description  Abs. Space Units
  4587.  
  4588.      m       meters       1.0
  4589.      mm      millimeters  0.0001
  4590.      cm      centimeters  0.01
  4591.      in      inches       0.02548
  4592.      ft      feet         0.3048
  4593.  
  4594. Screen
  4595.  
  4596. This opens a small window which enables control of the public screens used
  4597. by REAL 3D. It is opened automatically when a new screen is created to
  4598. provide a "handle" to the REAL 3D menus, until other windows have been
  4599. opened.
  4600.  
  4601. Gadgets of the screen window:
  4602.  
  4603. Default
  4604.  
  4605. Make active screen the default public screen.
  4606.  
  4607. Jump
  4608.  
  4609. Jump to next public screen. The control window will follow.
  4610.  
  4611. Close
  4612.  
  4613. Close all REAL 3D windows on the current screen then attempt to close the
  4614. screen. If other windows prevent the closure, then a warning requester
  4615. will be opened
  4616.  
  4617. Hijack
  4618.  
  4619. When enabled, windows and requesters opened for public screens will be
  4620. hijacked and opened on the default public screen. This allows other
  4621. applications which use public screens to be integrated into the REAL 3D
  4622. system. One possibility for this is to integrate a text editor for
  4623. creating and editing the text for RPL.
  4624.  
  4625.                             - REFERENCE 1.16 -
  4626.  
  4627. Pop-to-front
  4628.  
  4629. When windows and requesters are opened on the default public screen, it
  4630. will be brought to the front.
  4631.  
  4632. Close
  4633.  
  4634. Close the currenCy selected window. Some windows, for example a
  4635. borderless-View, do not have a close gadget. This function enables all
  4636. windows to be closed.
  4637.  
  4638. * No Gadgets
  4639.  
  4640. This function removes all the gadgets for controlling the View window to
  4641. leave a window with a narrow surrounding border. This window cannot be
  4642. moved or re-sized until this function is selected again.
  4643.  
  4644. Environment/
  4645.  
  4646. "Environment consists of the following data sections:
  4647. - screens
  4648. - windows (including Measuring system)
  4649. - global settings:
  4650. - frame buffer library name
  4651. - save format for frame buffer (tga, iff, ...)
  4652. - RPL initial configuration
  4653. - current tool name for modify system
  4654. - current register and RGB color
  4655. - operation level
  4656. - settings for modify subsystem
  4657. - default directory paths for projects, objects, textures etc.
  4658. - aspect ratio
  4659. - hot-point
  4660. - undo settings
  4661. - load/save sections
  4662. - sections
  4663. - vector/float format strings
  4664. - file name for current macro
  4665. - minimum dragging time
  4666. - default settings for fractal generators
  4667.  
  4668. Open Screen
  4669.  
  4670. Open new REAL 3D screen using Screen-settings requester.
  4671.  
  4672. Make Def.Pub.
  4673.  
  4674. Make currenCy selected screen the default public screen.
  4675.  
  4676. Close Screen
  4677.  
  4678. Close selected REAL 3D screen.
  4679.  
  4680. Close Current
  4681.  
  4682. Close any windows currently open on active screen and then attempt to
  4683. close the screen. If other programs have opened windows on the REAL 3D
  4684. screen, then the screen cannot be closed and the user will be warned.
  4685.  
  4686. Insert
  4687.  
  4688. Load a new environment definition from the file specified. This will
  4689. create a set of windows and screens in addition to the existing ones.
  4690.  
  4691. Save
  4692.  
  4693. Save the complete environment definition to the file specified.
  4694.  
  4695. Replace
  4696.  
  4697. Delete existing environment definition before loading the specified
  4698. environment file.
  4699.  
  4700. Save Screen
  4701.  
  4702. Open a File Requester and then save the active-screen as the specified
  4703. IFF file.
  4704.  
  4705.                             - REFERENCE 1.17 -
  4706.  
  4707. Screen Palette
  4708.  
  4709. Figure R1-7: Screen Palette Requester  (PICTURE: R1-7)
  4710.  
  4711. Open a requester enabling the active screen colors to be changed. The
  4712. screen register color to modify is selected from the color spectrum,
  4713. then it can be adjusted using the RGB sliders. Two pre-defined palette
  4714. definitions can be loaded
  4715.  
  4716. by selecting either of the two button-gadgets. The "COLOR SCALE"
  4717. definition is used with Render Settings/"Color Shading". Screen palettes
  4718. are saved as part of the screens data section.
  4719.  
  4720. External Screen/
  4721.  
  4722. These functions enable a library for controlling an External screen, like
  4723. a frame buffer, to be used.
  4724.  
  4725. Open
  4726.  
  4727. Open an External screen with its specified External screen library.
  4728.  
  4729. Close
  4730.  
  4731. Close External screen and its library.
  4732.  
  4733. Set Modes
  4734.  
  4735. This function allows settings of an External screen to be modified. Not
  4736. all libraries need this function, and so will not produce a requester.
  4737.  
  4738. Settings
  4739.  
  4740. Opens External screen requester allowing the user to select External
  4741. screen library and file format.
  4742.  
  4743. Figure R1-8: External Screen Settings Requester  (PICTURE: R1-8)
  4744.  
  4745. Gadgets of the External screen requester:
  4746.  
  4747. Library
  4748. Name of External screen library.
  4749.  
  4750. IFF24
  4751. IFF 24 file format used.
  4752.  
  4753. TARGA
  4754. Targa file format used.
  4755.  
  4756. TARGA+A-
  4757. Targa file format with alpha-information used for saving.
  4758.  
  4759.                             - REFERENCE 1.18 -
  4760.  
  4761. CUSTOM
  4762.  
  4763. External screen's own format.
  4764.  
  4765. Save
  4766.  
  4767. Save image from External screen using format specified by settings.
  4768.  
  4769. Exit Real
  4770.  
  4771. Close all REAL 3D windows and screens and return to WB. If other programs
  4772. have opened windows or requesters on any of REAL 3D's public screens, then
  4773. the program will warn the user and leave the screens open.
  4774.  
  4775. 1.2 CREATE
  4776.  
  4777. Creating the various primitive and compound-objects is carried out by
  4778. selecting the function and then supplying the appropriate data
  4779. coordinates. This is usually carried out with the mouse. The <LMB> defines
  4780. the View in which the operation will be carried out, selects the first
  4781. coordinate and starts the operation. It also defines consecutive
  4782. coordinates. The <RMB> completes a phase of the function. This may either
  4783. move onto the next phase, complete the creation, or cancel the whole
  4784. function. The first component of each primitive is ALWAYS created on the
  4785. input plane. Those components with depth are then extruded perpendicular
  4786. to the input plane. The direction of extrusion is determined using the
  4787. Right Hand Rule.
  4788.  
  4789. All 2D primitives, such as rectangle, circle and polygon, contain a small
  4790. stick called as "dvect", which describes the volume defined by the
  4791. primitive. This information is needed when object is used in Boolean
  4792. operations. 2D primitives divide the space to two different parts and the
  4793. dvect describes which side is the inside of the primitive. This means that
  4794. REAL 3D can handle infinite solids and they don't have to be closed (some
  4795. other solid modelling packages require that the solid must be closed, so
  4796. it is not possible to get inside it without passing through surfaces used
  4797. for defining it).
  4798.  
  4799. Visibles/
  4800.  
  4801. This sub-menu contains all the creation functions for the basic visible
  4802. primitives.
  4803.  
  4804. Polygon
  4805.  
  4806. PRIMITIVE: polygon
  4807. Create polygonal plane.
  4808. DEFINE: three or more points on a polygon.
  4809.  
  4810. Terminating the function before creating 3rd point cancels the creation.
  4811.  
  4812. Polyhedron
  4813.  
  4814. PRIMITIVE: polyhedron
  4815. Create polygonal prism.
  4816. DEFINE: polygonal cross-section.
  4817.  
  4818. The cross-section is extruded to defined depth.
  4819.  
  4820. Polymid
  4821.  
  4822. PRIMITIVE: polymid
  4823. Create polygonal based pyramid.
  4824. DEFINE: polygonal base and apex.
  4825.  
  4826. Cut polymid
  4827.  
  4828. PRIMITIVE: cut-polymid
  4829. Create polygonal based pyramid with truncated apex.
  4830.  
  4831. Figure R1-9: Polygon-based Visibles  (PICTURE: R1-9)
  4832.  
  4833.                             - REFERENCE 1.19 -
  4834.  
  4835. DEFINE: polygonal base, center of truncating surface and radial size of
  4836. truncating surface.
  4837.  
  4838. Figure R1-10: Rectangle-based Visibles  (PICTURE: R1-10)
  4839.  
  4840. Rectangle
  4841.  
  4842. PRIMITIVE: rectangle
  4843. Create rectangular plane.
  4844. DEFINE: two coordinates of diagonally opposite corners of rectangle.
  4845.  
  4846. Cube
  4847.  
  4848. PRIMITIVE: cube
  4849. Create rectangular prism.
  4850. DEFINE: rectangular cross-section. The cross-section is defined as for
  4851. rectangle. On completion, the rectangle is extruded to depth.
  4852.  
  4853. Pyramid
  4854.  
  4855. PRIMITIVE: pyramid
  4856. Create rectangular based prism.
  4857. DEFINE: rectangular base and apex.
  4858.  
  4859. Cut pyramid
  4860.  
  4861. PRIMITIVE: cut-pyramid
  4862. Create rectangular based prism with truncated apex.
  4863. DEFINE: two separate rectangles. The two rectangles form the two parallel
  4864. surfaces with additional planes created automatically for the sides.
  4865.  
  4866.  
  4867.  
  4868.                 END OF PART 4
  4869.  
  4870.  
  4871.  
  4872.  
  4873.  
  4874.  
  4875.